最近学习了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#中几种创建对象的方式的对比的更多相关文章

  1. Java中两种实现多线程方式的对比分析

    本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...

  2. Javascript学习笔记:9种创建对象的方式

    最基本的对象创建方式是通过Object构造函数或对象字面量的方式创建: ①通过Object构造函数的方式创建对象: var person=new Object();//或者写成var person={ ...

  3. mybatis中两种取值方式?谈谈Spring框架理解?

    1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...

  4. 转 java中5种创建对象的方法

    作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有5种创建对象的方式,下面给出它们的 ...

  5. 深入浅出spring IOC中三种依赖注入方式

    深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...

  6. 转:深入浅出spring IOC中四种依赖注入方式

    转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...

  7. [转载]C++中四种强制类型转换方式

    C++中四种强制类型转换方式 原文地址:http://www.cnblogs.com/home123/p/6763967.html 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单( ...

  8. JS高级---三种创建对象的方式

    JS高级---三种创建对象的方式 字面量的方式 (实例对象) 调用系统的构造函数 自定义构造函数方式 //创建对象---->实例化一个对象,的同时对属性进行初始化 var per=new Per ...

  9. Linux下几种常见压缩方式测试对比

    目录 Linux下几种常见压缩方式测试对比 参考 简介 测试 总结 Linux下几种常见压缩方式测试对比

随机推荐

  1. 常用lua代码块

    1.读取请求体中参数 local request_method = ngx.var.request_method local args --获取参数的值 if "GET" == r ...

  2. leetcode338—Counting Bits

    Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the ...

  3. springbatch入门练习(第二篇)

    对第一遍内容的补充 <?xml version="1.0" encoding="UTF-8"?> <bean:beans xmlns=&quo ...

  4. P3195 [HNOI2008]玩具装箱TOY

    列出DP方程式:设f[i]表示分组完前i件物品的最小花费,为方便计算,设sum[i]表示是前i件物品的长度和. f[i]=min(f[j]+(sum[i]-sum[j]+i-j-L-1)^2) [0& ...

  5. 609E- Minimum spanning tree for each edge

    Connected undirected weighted graph without self-loops and multiple edges is given. Graph contains n ...

  6. OO第1~3次作业总结

    作业1——多项式运算 基于度量和类图分析设计 先看Metrics插件做出的复杂度分析: 乍一看没有红色报警,其实是因为选中某一行时会自动将该行改为黑色,无论之前是红色还是蓝色emmm 真正展开第一行时 ...

  7. 二,ESP8266 GPIO和SPI和定时器和串口(基于Lua脚本语言)

    https://www.cnblogs.com/yangfengwu/p/7514336.html 我们写lua用这个软件 如果点击的时候提示安装,,安装就行,,如果没有提示呢可以,按照下面链接的提示 ...

  8. C# 取两个集合的交集\并集\差集

    交集:Intersect 并集:Union 差集:Except , , , , , }; , , , ,,, }; var C= A.Intersect(B); //交集 { 3, 4, 5, 6 } ...

  9. ubuntu14.04安装jupyter notebook

    1.使用pip安装Jupyter notebook: pip install jupyter notebook 2.创建Jupyter默认配置文件: jupyter notebook --genera ...

  10. mysql图形化界面MySQL_Workbench

    1,下载最新版本的MySQL Workbench,下载地址: http://www.mysql.com/downloads/workbench/   2,安装Workbench的依赖组件两个 http ...