C#中几种创建对象的方式的对比
最近学习了msil,发现了很多好玩的,今天介绍一个用IL来创建对象的方式
1.最常见的两种创建对象方式
public static T Create<T>() where T : new()
{
return new T();
}
public static object CreateNative()
{
return new object();
}
写一个测试帮助方法简单的测试下这两个方法的执行时间的长短:
public static void Measure(string what, int reps, Action action)
{
action(); //warm up
double[] results = new double[reps];
for (int i = 0; i < reps; i++)
{
Stopwatch sw = Stopwatch.StartNew();
action();
results[i] = sw.Elapsed.TotalMilliseconds;
}
Console.WriteLine("{0} - AVG = {1}, MIN = {2}, MAX = {3}", what,
results.Average(), results.Min(), results.Max());
}
调用测试方法:
int reps = 5;
int its = 100000;
Measure("create", reps, () =>
{
for (int i = 0; i < its; i++)
{
Create<object>();
}
});
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Measure("createNative", reps, () =>
{
for (int i = 0; i < its; i++)
{
CreateNative();
}
});
执行结果:

可以通过测试结果看出来本地方法创建的比泛型方式创建的消耗的时间短,这是为什么。用工具查看生成的il就可以发现为什么了。
泛型方式生成的IL如下:

本地方式的生成IL如下:

可以看出泛型方式生成的IL里面调用了Activator.CreateInstance方法,而本地方式而直接new一个对象。所以本地方式的生成对象要比泛型方式用时短。既然这样直接通过Activator.CreateInstance 生成对象呢。
2.Activator.CreateInstance方式生成对象
public static object CreateReflect(Type type)
{
return Activator.CreateInstance(type);
}
现在再来比较这三种的生成方式的用时长短,用同样的方式调用CreateReflect,得到结果如下:

从结果上看可以看出最快的是本地直接new,第二快是通过Activator.CreateInstance,最慢的则是泛型实例化创建对象。
在工作中泛型创建对象很常见。如何解决泛型创建对象慢的问题呢?
3.使用IL来创建泛型对象
public class CreationHelper<T> where T : new()
{
public static Func<T> objCreator = null;
public static T New()
{
if (objCreator == null)
{
Type objectType = typeof(T);
ConstructorInfo defaultCtor = objectType.GetConstructor(new Type[] { });
DynamicMethod dynMethod = new DynamicMethod(
name: string.Format("_{0:N}", Guid.NewGuid()),
returnType: objectType,
parameterTypes: null);
var gen = dynMethod.GetILGenerator();
gen.Emit(OpCodes.Newobj, defaultCtor);
gen.Emit(OpCodes.Ret);
objCreator = dynMethod.CreateDelegate(typeof(Func<T>)) as Func<T>;
}
return objCreator();
}
}
用以上相同的方式来测试,测试代码:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Measure("DynamicCreate", reps, () =>
{
for (int i = 0; i < its; i++)
{
CreationHelper<object>.New();
}
});
测试结果如下:

结果一目了然,IL方式创建对象的用时在本地实例化和Activator.CreateInstance之间,只比本地实例化稍慢。所以泛型实例化可以考虑这种方式,可以提升泛型实例化的效率。
4.总结
本文介绍了c#创建对象的4种方式,简单的比较了这四种创建效率。说明了IL的效率果然是高。学会了高效的创建泛型对象的一种方式。
C#中几种创建对象的方式的对比的更多相关文章
- Java中两种实现多线程方式的对比分析
本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...
- Javascript学习笔记:9种创建对象的方式
最基本的对象创建方式是通过Object构造函数或对象字面量的方式创建: ①通过Object构造函数的方式创建对象: var person=new Object();//或者写成var person={ ...
- mybatis中两种取值方式?谈谈Spring框架理解?
1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...
- 转 java中5种创建对象的方法
作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有5种创建对象的方式,下面给出它们的 ...
- 深入浅出spring IOC中三种依赖注入方式
深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...
- 转:深入浅出spring IOC中四种依赖注入方式
转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...
- [转载]C++中四种强制类型转换方式
C++中四种强制类型转换方式 原文地址:http://www.cnblogs.com/home123/p/6763967.html 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单( ...
- JS高级---三种创建对象的方式
JS高级---三种创建对象的方式 字面量的方式 (实例对象) 调用系统的构造函数 自定义构造函数方式 //创建对象---->实例化一个对象,的同时对属性进行初始化 var per=new Per ...
- Linux下几种常见压缩方式测试对比
目录 Linux下几种常见压缩方式测试对比 参考 简介 测试 总结 Linux下几种常见压缩方式测试对比
随机推荐
- OpenCV——反向投影(定位模板图像在输入图像中的位置)
反向投影: #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namesp ...
- OpenCV——凸包
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ...
- Kafka设计解析(二十三)关于Kafka监控方案的讨论
转载自 huxihx,原文链接 关于Kafka监控方案的讨论 目前Kafka监控方案看似很多,然而并没有一个“大而全”的通用解决方案.各家框架也是各有千秋,以下是我了解到的一些内容: 一.Kafka ...
- array_multisort函数,以及多维数组下排序的应用,并与usort函数对比
以前比较少用这个函数,大部分自己接触的业务里,处理稍微大一些的数组的时候几乎都是从db里取出来的,在db里就order by了. 最近倒是用了次,这个函数用来排序很强大,有点类似于sql中的order ...
- python基础——类定义(转)
一.类定义: class <类名>: <语句> 类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性.如果直接使用类名修改其属性,那么将直接影响到已经实例 ...
- 20155301 Exp7 网络欺诈防范
20155301 Exp7 网络欺诈防范 1.基础问题回答 (1)通常在什么场景下容易受到DNS spoof攻击 (2)在日常生活工作中如何防范以上两攻击方法 2.实践过程记录 简单应用SET工具建立 ...
- python 回溯法 子集树模板 系列 —— 13、最佳作业调度问题
问题 给定 n 个作业,每一个作业都有两项子任务需要分别在两台机器上完成.每一个作业必须先由机器1 处理,然后由机器2处理. 试设计一个算法找出完成这n个任务的最佳调度,使其机器2完成各作业时间之和达 ...
- Codeforces 734E Anton and Tree(缩点+树的直径)
题目链接: Anton and Tree 题意:给出一棵树由0和1构成,一次操作可以将树上一块相同的数字转换为另一个(0->1 , 1->0),求最少几次操作可以把这棵数转化为只有一个数字 ...
- springtest mapper注入失败问题解决 {@org.springframework.beans.factory.annotation.Autowired(required=true)}
花费了一下午都没有搜索到相关解决方案的原因,一是我使用的 UnsatisfiedDependencyException 这个比较上层的异常(在最前面)来进行搜索, 范围太广导致没有搜索到,而且即便是有 ...
- stl源码剖析 详细学习笔记 hashset hashmap
//---------------------------15/03/26---------------------------- //hash_set { /* hash_set概述: 1:这是一个 ...