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下几种常见压缩方式测试对比
随机推荐
- scrapy shell
一.scrapy shell 1.安装pip install Jupyter 2.在pycharm中的启动命令: scrapy shell 注:启动后关键字高亮显示 3.查看response 执行sc ...
- loadrunner中pacing设置01
之前一直也用pacing值来调节TPS,一直觉得它和think time没啥区别.这次项目中,和同事就此展开了讨论,细细一研究发现pacing值门道还是很多的. 如下面三个图: 上图是pacing的三 ...
- Web.config中 mode="RemoteOnly" 跟mode="On" 区别
转载网址:mode="RemoteOnly" 跟mode="On" 区别 <!-- 自定义错误信息 设置 customErrors mode=" ...
- office2016word 每次打开都有进度条问题 解决方式
最佳答案 每次打开Office 2016都提示配置进度(包括Word.PPT.Excel等等Office产品都有这种现象),如图,先是显示“安装程序正在准备必要的文件”,接着显示“正在配置Mi ...
- android获取内置和外置SD卡路径 - z
本文将介绍Android真机环境下如何获取内置和外置SD卡路径. 测试环境:三星Note3,其他手机待测试... 所需权限(AndroidManifest.xml文件里) <uses-permi ...
- [agc011C]Squared Graph-[二分图]
Description 传送门 Solution 我们以下考虑的情况都是原图中非孤立的点. 题目要求新图的连通块个数.这个不好算,我们考虑计算新图的联通块内的特征点(x,y),即无法通过移动找到(t, ...
- debian系统下改语言设置
debian系统下改语言设置 安装debian 的时候选择了中文zh_CN_UTF-8,然后进系统后想换成en_US_UTF-8 可以使用一下命令选择:找到需要的语言 确定即可 dpkg-reconf ...
- CF434D Nanami's Power Plant
就是切糕那道题,首先对每个函数连一串,然后\(x_u\leq x_v+d\)这个条件就是\(u\)函数\(i\)取值连向\(v\)函数\(i-d\)取值边权为inf,然后答案就是最小割了. #incl ...
- NodeMCU学习(四):与其他设备通信
TCP连接 TCP是计算机网络中运输层协议,是应用层协议http协议的支撑协议.两台远程主机之间可以通过TCP/UDP协议进行通信并交换信息,前提是,相互通信的两台主机之间必须知道彼此的IP地址和端口 ...
- Linux下的信号详解
文章链接:https://blog.csdn.net/qq_38646470/article/details/80257512