WEB开发网      婵犵數濞€濞佳囧磹婵犳艾鐤炬い鎰堕檮閸嬬喐銇勯弽銊с€掗梻鍕閺岋箑螣娓氼垱笑闂佽姘﹂褔婀佸┑鐘诧工妤犲憡绂嶉崜褏纾奸弶鍫涘妼缁楁岸鏌熷畡鐗堝殗闁诡喒鏅犲畷褰掝敃閵堝棙顔忔繝鐢靛仦閸ㄥ爼骞愰幘顔肩;闁规崘绉ぐ鎺撳亹闁绘垶锕╁Λ鍕⒑閹肩偛濡奸悗娑掓櫇缁顓兼径妯绘櫇闂佹寧绻傞弻濠囨晝閸屾稓鍘甸柣搴㈢⊕閿氶柣蹇ョ稻缁绘繃绻濋崘銊т紝闂佽鍨伴崯鏉戠暦閻旂⒈鏁傞柛鈾€鏅欑槐妯衡攽閻愬樊鍤熷┑顔藉劤铻為柛鏇ㄥ墯閸欏繘鏌嶉崫鍕櫣缂佲偓婢跺绠鹃柟瀛樼箘閿涘秵顨ラ悙顏勭伈闁诡喖缍婂畷鎯邦槻婵℃彃顭烽弻娑㈠Ω閵夈儺鍔夌紓浣稿€哥粔褰掑极閹剧粯鏅搁柨鐕傛嫹 ---闂傚倷鐒︾€笛兠洪埡鍛闁跨噦鎷�
开发学院WEB开发ASP .Net中各种不同的对象创建方式的速度差异(四) 阅读

.Net中各种不同的对象创建方式的速度差异(四)

 2010-02-25 10:45:52 来源:WEB开发网 闂傚倷绶氬ḿ褍螞閹绢喖绠柨鐕傛嫹闂傚倷绀侀幉锟犲垂閻㈠灚宕查柟鎵閸庡秵銇勯幒鎴濃偓鐢稿磻閹炬枼妲堟繛鍡楃С濞岊亞绱撻崒姘扁枌闁瑰嚖鎷�婵犵數濮幏鍐川椤撴繄鎹曢梻渚€娼уú銈吤洪妸鈺佺劦妞ゆ帊鑳堕埊鏇㈡煏閸モ晛浠х紒杈╁仱閺佹捇鏁撻敓锟�闂傚倷绶氬ḿ褍螞閹绢喖绠柨鐕傛嫹  闂傚倷鑳舵灙缂佺粯顨呴埢宥夊即閵忕姵鐎梺缁樺姇閻忔氨鈧凹鍓熷娲垂椤曞懎鍓伴梺閫炲苯澧紒澶婄秺瀵濡歌閸嬫捇妫冨☉娆忔殘闂佷紮缍€娴滎剟鍩€椤掑倹鏆柛瀣躬瀹曚即寮借閺嗭箓鏌ㄩ悤鍌涘
核心提示:本文章为本人个人博客相应文章的镜像:原文地址: http://www.greatony.com/index.php/2010/02/24/speed-of-object-creation-in-dotnet-iv/ 在这片文章中,我们暂时放一放Activator.CreateInstance(Type)和Activat
本文章为本人个人博客相应文章的镜像:

原文地址: http://www.greatony.com/index.php/2010/02/24/speed-of-object-creation-in-dotnet-iv/

在这片文章中,我们暂时放一放Activator.CreateInstance(Type)和Activator.CreateInstance<T>()之间的性能差异,去探索一下,为什么使用泛型约束的速度和CreateInstance<T>()差不多(用屁股都能猜到应该是直接调用了CreateInstance<T>())。




首先我们写一个小程序来验证我们的猜想:

1 using System;
2
3 namespace GenericNew
4 {
5   public class PRogram
6   {
7     public static void Main(string[] args)
8     {
9       CreateInstance<Program>();
10       new Program();
11     }
12   
13     public static T CreateInstance<T>() where T: new()
14     {
15       return new T();
16     }
17   }
18 }


编译了以后用reflector来查看编译的结果:

1 public static T CreateInstance<T>() where T: new()
2 {
3   return new T();
4 }
5


看起来没有什么问题啊,跟写的时候一样美妙,也没有见到System.Activator.CreateInstance<T>()的踪影。

那么,让我们切换到msil模式看看:

1 .method public hidebysig static !!T CreateInstance<.ctor T>() cil managed
2 {
3   .maxstack 2
4   .locals init (
5     [0] !!T local,
6     [1] !!T local2)
7   L_0000: nop
8   L_0001: ldloca.s local2
9   L_0003: initobj !!T
10   L_0009: ldloc.1
11   L_000a: box !!T
12   L_000f: brfalse.s L_001c
13   L_0011: ldloca.s local2
14   L_0013: initobj !!T
15   L_0019: ldloc.1
16   L_001a: br.s L_0021
17   L_001c: call !!0 [mscorlib]System.Activator::CreateInstance<!!T>()
18   L_0021: stloc.0
19   L_0022: br.s L_0024
20   L_0024: ldloc.0
21   L_0025: ret
22 }


恩,发现[mscorlib]System.Activator::CreateInstance<!!T>()了,通过分析这段代码,我们会发现,其实ms对于这个的性能还是做了一定的优化的,这段代码:



试图采用值类型的初始化方法初始化对象,并对该对象进行装箱操作
装箱失败的情况下,调用System.Activator.CreateInstance<T>()来创建对象


最后再返回创建好的对象。

那么是不是.net本来就是通过这种方式来创建对象的呢?

我们来对比一下new Program()这条语句的编译结果:

1 newobj instance void GenericNew.Program::.ctor()



那么为什么c#编译器没有采用这个指令来创建泛型类的实例呢?

我们需要参考一下msdn上对于newobj的用法的定义:

http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.newobj(VS.85).aspx

在这里,我们看到,newobj指令的使用方法是 newobj <ctor>

也就是说,它的参数是构造器,而非类型本身; 原因就在于,.Net允许有不同参数的构造器存在,只有指定了构造器,clr才知道要使用哪个构造器来初始化对象。

而,对于一个泛型类,在编译器是无法知道它的泛型参数的构造器信息的,自然就没有办法使用newobj指令了。




这就是事实的真相,在下一篇文章中,我们将去探究,事实的终极真相。

Tags:Net 各种 不同

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接