IList<;的TypeDependencyAttribute(“System.SZArrayHelper”)的目的

本文关键字:SZArrayHelper System lt TypeDependencyAttribute IList | 更新日期: 2023-09-27 18:21:18

IList、IEnumerable和ICollection的源代码中提供的注释表示

注意T[] : IList<T>,我们希望确保如果您使用IList<YourValueType>,我们确保可以使用YourValueType[]没有抖动。因此CCD_ 4在CCD_。这是一个特殊的内部破解-请参阅VM''compaile.cpp.

为什么IList<T>包含对SZArrayHelper的依赖项?。我知道SZArrayHelper是一个CLR包装器,它围绕着一个实现IList<T>接口的数组,但我不知道为什么这两者结合在一起。

它如何确保YourValueType[]可以在不抖动的情况下使用。?

IList<;的TypeDependencyAttribute(“System.SZArrayHelper”)的目的

正如您的报价中所指出的,这是JIT中的一次黑客攻击。当VM发现SZArrayHelper上有一个TypeDependency时,它会以不同的方式处理该类,从而允许使用更高效的代码。

查看VM中的相关代码(请注意,我在这里使用的是较旧的公共版本,而不是实际的.NETVM):

必须特别处理通过IList(或IEnumerable或ICollection)对数组的调用。这些接口是"神奇的"(主要是由于相关的工作集——它们是根据内部需求创建的即使在语义上,这些都是静态接口。)

数组首先在.NET中有点像黑客。当添加通用接口时,这带来了一些问题——例如,int[]Array,但它也是一种特殊类型,是int的数组;这允许数组在添加real泛型类型之前是泛型的。

现在,让我们来看一个具体的例子。您有一个int[],并且希望在LINQ中使用它。由于int[]实现了IEnumerable<int>,它为您提供了开箱即用的LINQ的全部功能,您可以编写以下内容:

var positiveNumbers = numbers.Where(i => i > 0);

从C#的角度来看,这是没有问题的。然而,从VM的内部来看,这是一个很大的问题,因为int[]实际上并没有实现IEnumerable<int>!即使在将泛型引入.NET(和C#)之后,数组仍然以旧的方式处理。

破解是使用SZArrayHelper来处理这些通用方法中的任何一个。因此,例如,WhereIEnumerable<int>上内部调用GetEnumerator。虚拟机发现您正试图在数组上调用GetEnumerator,它并没有在数组实例上实际调度GetEnumerator,而是将调用重定向到SZArrayHelper.GetEnumerator<int>()

这是一个巨大的破解-如果你查看SZArrayHelper的参考代码,你会发现大量警告-例如,GetEnumerator<int>方法是一个实例方法,但它的this参数实际上是数组(例如int[]),而不是SZArrayHelper

但它允许我们将数组视为它们确实实现了所有这些通用接口——即使它们没有:)