问题 System.Array是否对值类型执行装箱?


我最近做了一些粗略的表现测量 List<> VS [] 对于一系列小结构。 System.Array似乎赢得了胜利,所以我顺其自然。

只是我突然意识到System.Array包含对象类型,所以肯定用结构填充它会导致拳击发生?

然而, System.Array的MSDN条目 状态:

在.NET Framework 2.0版中,Array类实现了    System.Collections.Generic.IList<T>,    System.Collections.Generic.ICollection<T>,和    System.Collections.Generic.IEnumerable<T> 通用接口。该   实现在运行时提供给数组,因此是   文档构建工具不可见。结果,通用   接口不会出现在Array的声明语法中   类,并没有接口成员的参考主题   只能通过将数组转换为通用接口类型来访问   (显式接口实现)。

这是否意味着毕竟不会发生拳击? (并会解释我的表现结果)


11072
2017-11-21 15:07


起源

为了解释您的性能结果,我们可能会看到您用来衡量性能的代码。 - Snowbear


答案:


如果使用索引器表示法,则不使用数组。 例如

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

对于不能使用索引器的语言(我真的不知道它们是否存在),在编译时为数组创建了2个其他方法。

它创建了这些公共方法::

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

这些方法既不会封装,也不能通过C#访问。 (不要问我为什么他们是公共方法)。您可以使用IL或通过创建委托来执行它们。当你被迫做一个callvirt来调用这些方法时,它们会变慢。

stelem。*和ldelem。*系列用于处理存储为强类型数组的类型。使用泛型时,通常会附加以下前缀 constrained 要么 readonly 使用时 T[]stelem.* 类型通常不检查类型。例如。运用 stelem.i4 比使用更快 stelem.any Int32 除非你用它作为前缀 readonly 因为否则会强制进行类型检查。

现在,对于valuetype数组,类型检查完全没用,它们是不协变的!

因为运行时生成从零开始的一维数组(称为SZ_array或矢量类型)类型,所以它们本身是已知的。

有一系列il op代码: newarrstelem.*ldelem.*ldlen 等等

List<T> 类型使用a T[] 为其在BCL的微软实施中的后备存储。 List<T> 没有盒子。无论使用列表还是数组,都要将数据存储在数组中。


12
2017-11-21 16:05



这是关于数组的堆/堆栈分配及其包含值的另一个答案的补充链接: stackoverflow.com/questions/1113819/... - BoltClock♦
由于Arrays是引用类型,因此unboxed int也存储在托管堆中 - 没有任何内容可供使用。 - Alex