2011-11-21 53 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