最近学习了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. 使用Java线程并发库实现两个线程交替打印的线程题

    背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题.晚上闲着没事就决定把它实现出来. 题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交 ...

  2. 多模匹配算法之Aho-Corasick

    除剔除那些含有敏感词的文本,由于有大量的敏感词,所以通过简单的正则表达式和字符串查找的方式效率太低,每次都有遍历一次字符串.而AC算法的核心思想就是避免不必要的回溯使搜索一直沿着向前的方向,最大可能的 ...

  3. DDD China Conference 2017

    DDD China Conference 2017 时间:2017.12.9地点:国际会议中心

  4. eclipse 最最最常用快捷键

    使用eclipse这么久,发现其跟PS一样,使用一些快捷键会有效率很多. 至此总结出以下每次打开eclipse基本都会用上的快捷键. 不熟悉这些快捷键,在实际编程中有意识使用的话对以后编码很有帮助. ...

  5. zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。

    zooland 我叫它动物园地,一个构思很长时间的一个项目.起初只是觉得各种通信框架都封装的很好了,但是就是差些兼容,防错,高可用.同时在使用上,不希望有多余的代码,像普通接口一样使用就可以了. 基于 ...

  6. react脚手架改造(react/react-router/redux/eslint/karam/immutable/es6/webpack/Redux DevTools)

    公司突然组织需要重新搭建一个基于node的论坛系统,前端采用react,上网找了一些脚手架,或多或少不能满足自己的需求,最终在基于YeoMan的react脚手架generator-react-webp ...

  7. Hexo站点之域名配置【2】

    该系列博客列表请访问:http://www.cnblogs.com/penglei-it/category/934299.html 摘要 因为Hexo个人博客是托管在github之上,每次访问都要使用 ...

  8. 重磅发布丨乐维监控:全面兼容云平台,助力企业DevOps转型升级!

    2019年伊始,我们迎来了乐维监控的又一重大功能更新——云平台监控,这将有效帮助企业将云上.云下数据聚合,方便统一化的监控管理与维护!未来,乐维监控每一次的产品功能及版本更新,我们都将第一时间于此发布 ...

  9. EOS开发基础之一:源代码下载与开发环境搭建

    区块链最近挺火的,我又是个非常缺钱的人,所以紧跟了潮流一头扎进区块链的研究中. 这EOS项目是目前比较火的一个项目,相信很多朋友拿到这份EOS的源代码后都会一脸懵逼,因为……这代码写得太高级了,老纸看 ...

  10. Pipeline Alpha版本项目展示

    团队成员简介:http://www.cnblogs.com/cheneygroup/p/4830994.html 团队成员及博客: 李剑锋:        Blog:      http://www. ...