2011-11-21 55 views
11

我最近在List<>[]上做了一些粗略的性能測試,測試了一系列小結構。 System.Array似乎贏了手,所以我去了。System.Array是否對值類型執行裝箱操作?

它只是在我身上才明白System.Array包含對象類型,所以肯定用結構填充它會導致出現裝箱?

然而,the MSDN entry for System.Array狀態:

在.NET Framework 2.0版,Array類實現了 System.Collections.Generic.IList<T>System.Collections.Generic.ICollection<T>System.Collections.Generic.IEnumerable<T>通用接口。在運行時向陣列提供 實現,因此 對文檔構建工具不可見。因此,類 類的聲明語法中沒有出現通用的 接口,並且僅有通過將數組轉換爲通用接口類型 (顯式接口實現)才能訪問 的接口成員沒有參考主題。 。

這是否意味着拳擊不會發生? (並且會解釋我的性能結果)

+0

爲了解釋您的績效結果,我們可能應該看到您用來衡量績效的代碼。 – Snowbear

回答

12

如果使用索引器表示法,則不使用數組不會使用索引器表示法。 例如

new int[2]; 
x=[1]=3; 

編譯以下IL(注意行號是不相關的,因爲他們來自的其它代碼很有)

IL_0011: ldc.i4.2 
IL_0012: newarr System.Int32 
IL_0017: stfld Int32[] x 
IL_001c: ldarg.0 
IL_001d: ldfld Int32[] x 
IL_0022: ldc.i4.1 
IL_0023: ldc.i4.3 
IL_0024: stelem.i4 

對於不能使用索引的語言(我真的不知道它們是否存在)另外兩種方法是在編譯時爲數組創建的。

它創建這些公共方法::

public int Get(int index) 
public void Set(int index,int value) 

這些辦法也不框和通常不通過C#訪問。 (不要問我爲什麼他們是公共方法)。您可以使用IL或通過創建代理來執行它們。由於您被迫執行callvirt來調用這些方法,它們會比較慢。

stelem。*和ldelem。*系列用於處理存儲到強類型的數組類型。使用泛型時,通常在使用T[]時,附加以下前綴constrainedreadonlystelem.*類型通常不檢查類型。例如。使用stelem.i4比使用stelem.any Int32要快,除非您在readonly前面加上前綴,否則會強制進行類型檢查。

現在typecheck在valuetype數組上是完全無用的,它們不是協變的!

由於運行時生成從零開始(稱爲SZ_array或向量類型)類型的一維數組,它們本身是已知的。

有金正日的操作碼家族爲他們:newarrstelem.*ldelem.*ldlen

List<T>類型使用T[]在微軟實施BCL其後備存儲。 List<T>不包裝。無論使用列表還是陣列,您都將數據存儲在數組中。

+1

下面是有關堆棧/堆棧分配數組及其包含值的另一個答案的補充鏈接:http://stackoverflow.com/questions/1113819/arrays-heap-and-stack-and-value-types/1114152#1114152 – BoltClock

+1

由於數組是引用類型,因此拆箱後的int也存儲在託管堆中 - 沒有什麼可以提及的。 – Alex