详解C#实例化对象的三种方式及性能对比

前言

做项目过程中有个需求要实例化两万个对象并添加到List

中,这个过程大概需要1min才能加载完(传参较多),于是开启了代码优化之旅,再此记录。

首先想到的是可能实例化比较耗时,于是开始对每种实例化方式进行测试,过程如下

实例化方式

1、用 New 关键字实例化一个类

2、用 Activator 实例化一个类

3、用 Assembly 实例化一个类

代码实现

测试环境:

vs2019 .NET Framework 4.7

Intel Core i7-10510U CPU

首先定义一个类Person

public class Person
{
 public Person()
 {
 }
 public Person(string name)
 {
  Name = name;
 }
 public string Name { get; set; }
}

我们先在无参的构造函数中实例化,每种方式进行十次,每次实例化十万次,代码如下

static void Main(string[] args)
  {
   Console.WriteLine("实例化对象的耗时比较(单位:毫秒)");
   Console.Write("     ");
   for (int i = 1; i <= 10; i++)
    Console.Write("{0:G}", i.ToString().PadLeft(5));
   Console.Write("\n");
   Console.Write("InstanceByNew".PadRight(20));
   for (int i = 1; i <= 10; i++)
   {
    Person person = null;
    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int j = 0; j < 100000; j++)
     person = new Person();
    watch.Stop();
    Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
   }
   Console.Write("\n");
   Console.Write("InstanceByActivator".PadRight(20));
   for (int i = 1; i <= 10; i++)
   {
    Type type = Type.GetType("ConsoleApp1.Person");
    Person person = null;

    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int j = 0; j < 100000; j++)
    {
     object obj = Activator.CreateInstance(type);
     person = obj as Person;
    }
    watch.Stop();
    Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
   }
   Console.Write("\n");
   Console.Write("InstanceByAssembly".PadRight(20));
   for (int i = 1; i <= 10; i++)
   {
    Assembly assembly = Assembly.Load("InstancePerformance");
    Person person = null;

    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int j = 0; j < 100000; j++)
    {
     object obj = assembly.CreateInstance("ConsoleApp1.Person");
     person = obj as Person;
    }
    watch.Stop();
    Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
   }
   Console.Write("\n");
   Console.ReadKey();
  }

执行结果如下:

然后来看下有参构造函数中实例化的代码和结果

static void Main(string[] args)
  {
   Console.WriteLine("实例化对象的耗时比较(单位:毫秒)");
   Console.Write("     ");
   for (int i = 1; i <= 10; i++)
    Console.Write("{0:G}", i.ToString().PadLeft(5));
   Console.Write("\n");
   Console.Write("InstanceByNew".PadRight(20));
   for (int i = 1; i <= 10; i++)
   {
    Person person = null;
    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int j = 0; j < 100000; j++)
     person = new Person("Test"+j);
    watch.Stop();
    Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
   }
   Console.Write("\n");
   Console.Write("InstanceByActivator".PadRight(20));
   for (int i = 1; i <= 10; i++)
   {
    Type type = Type.GetType("ConsoleApp1.Person");
    Person person = null;

    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int j = 0; j < 100000; j++)
    {
     object obj = Activator.CreateInstance(type,new object[]{"Test"+j});
     person = obj as Person;
    }
    watch.Stop();
    Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
   }
   Console.Write("\n");
   Console.Write("InstanceByAssembly".PadRight(20));
   for (int i = 1; i <= 10; i++)
   {
    Assembly assembly = Assembly.Load("InstancePerformance");
    Person person = null;

    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int j = 0; j < 100000; j++)
    {
     object obj = assembly.CreateInstance("ConsoleApp1.Person", true, System.Reflection.BindingFlags.Default, null, new []{"Test"+j}, null, null);
     person = obj as Person;
    }
    watch.Stop();
    Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
   }
   Console.Write("\n");
   Console.ReadKey();
  }

执行结果如下:

结论

从上面的执行结果可以看出这三种方式的性能排序为

New > Activator > Assembly

但使用哪种方法还要视情况而定

后续

以上可以看出New性能最高,而我就是使用的New,问题还没解决,把问题指向判断List是否存在某元素上,于是开始测试List中的Contains, Exists, Any,Where。详情请点击.

到此这篇关于C#实例化对象的三种方式及性能对比的文章就介绍到这了,更多相关C#实例化对象的三种方式及性能对比内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C# 实例化接口对象的方法

    在head first 设计模式中 用到了很多很多接口对象 首先澄清一个问题,就是接口不仅可以声明对象,而且可以把对象实例化,还可以当做参数被传入. 一.接口回调 这就是继承中的向上转型.父类 FL=new 子类():只不过这里的父类就是interface接口.(个人认为这里不管是class的override还是interface的重写,都是一样的用法) 可以把实现某一接口类创建的对象的引用赋给该接口声明的接口变量,那么该 接口变量就可以调用被类实现的接口中的方法.实际上,当接口变量调用被类实现

  • 详解C#实例化对象的三种方式及性能对比

    前言 做项目过程中有个需求要实例化两万个对象并添加到List 中,这个过程大概需要1min才能加载完(传参较多),于是开启了代码优化之旅,再此记录. 首先想到的是可能实例化比较耗时,于是开始对每种实例化方式进行测试,过程如下 实例化方式 1.用 New 关键字实例化一个类 2.用 Activator 实例化一个类 3.用 Assembly 实例化一个类 代码实现 测试环境: vs2019 .NET Framework 4.7 Intel Core i7-10510U CPU 首先定义一个类Per

  • 详解Springboot下载Excel的三种方式

    汇总一下浏览器下载和代码本地下载实现的3种方式. (其实一般都是在代码生成excel,然后上传到oss,然后传链接给前台,但是我好像没有实现过直接点击就能在浏览器下载的功能,所以这次一起汇总一下3种实现方式.)

  • 详解Spring依赖注入的三种方式以及优缺点

    目录 0.概述 1.属性注入 1.1 优点分析 1.2 缺点分析 2.Setter 注入 优缺点分析 3.构造方法注入 优点分析 总结 0.概述 在 Spring 中实现依赖注入的常见方式有以下 3 种: 属性注入(Field Injection): Setter 注入(Setter Injection): 构造方法注入(Constructor Injection). 它们的具体使用和优缺点分析如下. 1.属性注入 属性注入是我们最熟悉,也是日常开发中使用最多的一种注入方式,它的实现代码如下:

  • 详解SpringBoot禁用Swagger的三种方式

    目录 摘要 方法 禁用方法1: 禁用方法2: 禁用方法3: 摘要 在生产环境下,我们需要关闭swagger配置,避免暴露接口的这种危险行为. 方法 禁用方法1: 使用注解 @Value() 推荐使用 package com.dc.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Be

  • 详解Spring获取配置的三种方式

    目录 前言 Spring中获取配置的三种方式 通过@Value动态获取单个配置 通过@ConfigurationProperties+前缀方式批量获取 通过Environment动态获取单个配置 总结 前言 最近在写框架时遇到需要根据特定配置(可能不存在)加载 bean 的需求,所以就学习了下 Spring 中如何获取配置的几种方式. Spring 中获取配置的三种方式 通过 @Value 方式动态获取单个配置 通过 @ConfigurationProperties + 前缀方式批量获取配置 通

  • 详解mysql数据去重的三种方式

    目录 一.背景 二.数据去重三种方法使用 1.​通过MySQL DISTINCT:去重(过滤重复数据) 2.group by 3.row_number窗口函数 三.总结 一.背景 最近在和系统模块做数据联调,其中有一个需求是将两个角色下的相关数据​对比后将最新的数据返回出去,于是就想到了去重,再次做一个总结. 二.数据去重三种方法使用 1.​通过MySQL DISTINCT:去重(过滤重复数据) ​ 1.1.在使用 mysql SELECT 语句查询数据的时候返回的是所有匹配的行. SELECT

  • SQLServer批量插入数据的三种方式及性能对比

    昨天下午快下班的时候,无意中听到公司两位同事在探讨批量向数据库插入数据的性能优化问题,顿时来了兴趣,把自己的想法向两位同事说了一下,于是有了本文. 公司技术背景:数据库访问类(xxx.DataBase.Dll)调用存储过程实现数据库的访问. 技术方案一: 压缩时间下程序员写出的第一个版本,仅仅为了完成任务,没有从程序上做任何优化,实现方式是利用数据库访问类调用存储过程,利用循环逐条插入.很明显,这种方式效率并不高,于是有了前面的两位同事讨论效率低的问题. 技术方案二: 由于是考虑到大数据量的批量

  • 详解Java实现多线程的三种方式

    本文实例为大家分享了Java实现多线程的三种方式,供大家参考,具体内容如下 import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class Main { public static void main(String[] args) { //方法一:继承Thread int i = 0; // for(; i < 100; i++){ // System.out.println(T

  • 详解SpringBoot 调用外部接口的三种方式

    目录 1.简介 2.方式一:使用原始httpClient请求 3.方式二:使用RestTemplate方法 4.方式三:使用Feign进行消费 1.简介 SpringBoot不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程.在Spring-Boot项目开发中,存在着本模块的代码需要访问外面模块接口,或外部url链接的需求, 比如在apaas开发过程中需要封装接口在接口中调用apaas提供的接口(像发起流程接口submit等等)下面也是

  • 详解iOS设置字体的三种方式

    有时候项目需要显示一些非系统的字体达到一些UI的效果,目前设置字体有三种方式,默认方式.bundle方式,coreText方式. 1 默认方式 这种方式就是正常的字体设置方式 label.font = [UIFont fontwithname:@"Blazed" size:42]; 至于第一个参数的名字,可以通过以下方法输出所有字体名字列表 [UIFont familyNames] 只要名字列表中存在的,都可以用这种方式关联到对应的字体上. 2 绑定自定义的字体包 其实第二种方式和第一

随机推荐