程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> ASP編程 >> ASP技巧 >> .Net中各種不同的對象創建方式的速度差異(四)

.Net中各種不同的對象創建方式的速度差異(四)

編輯:ASP技巧

在這片文章中,我們暫時放一放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指令了。

 


這就是事實的真相,在下一篇文章中,我們將去探究,事實的終極真相。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved