【问题标题】:Purpose of TypeDependencyAttribute("System.SZArrayHelper") for IList<T>, IEnumerable<T> and ICollection<T>?IList<T>、IEnumerable<T> 和 ICollection<T> 的 TypeDependencyAttribute("System.SZArrayHelper") 的用途?
【发布时间】:2015-11-11 16:17:15
【问题描述】:

source code 中为 IList、IEnumerable 和 ICollection 提供的 cmets 表示

注意T[] : IList&lt;T&gt;,我们要确保如果您使用 IList&lt;YourValueType&gt;,我们确保可以使用YourValueType[] 没有抖动。因此SZArrayHelper 上的TypeDependencyAttribute。 这是内部的特殊 hack - 请参阅 VM\compile.cpp。

为什么IList&lt;T&gt; 包含对SZArrayHelper 的依赖?我知道SZArrayHelper 是一个围绕实现IList&lt;T&gt; 接口的数组的CLR 包装器,但我不完全了解为什么这两者结合在一起。

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

【问题讨论】:

  • 可能是因为 99.9% 的集合在某种程度上使用数组进行存储,因此需要这种依赖关系是合理的。这会给您带来问题还是您只是好奇?
  • @DStandley:很好奇.. 但它又是如何确保 YourValueType[] 可以在不抖动的情况下使用的。?
  • 这与YourValueType[] 本身无关。它是关于在转换为相应的通用接口时使用它。 int[] 没有实际上实现了IEnumerable&lt;int&gt;.GetEnumerator,尽管它看起来好像实现了——实际的实现在那个神秘的SZArrayHelper 类中。

标签: c# .net


【解决方案1】:

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

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

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

数组首先是 .NET 中的一个小技巧。添加泛型接口时,这就带来了一点问题——例如int[]是一个Array,但它也是一个特殊类型,并且是int数组;这允许数组在添加 real 泛型类型之前是泛型的。

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

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

从 C# 的角度来看,没有问题。然而,从虚拟机内部的角度来看,这一个大问题,因为int[] 实际上没有实现IEnumerable&lt;int&gt;!即使在 .NET(和 C#)中引入了泛型,数组仍然以旧方式处理。

技巧是使用SZArrayHelper 来处理任何这些通用方法。因此,例如,WhereIEnumerable&lt;int&gt; 内部调用GetEnumerator。 VM 发现您正在尝试在阵列上调用 GetEnumerator,而不是在阵列实例上虚拟分派 GetEnumerator,而是将调用重定向到 SZArrayHelper.GetEnumerator&lt;int&gt;()

这是一个巨大 hack - 如果您查看SZArrayHelper 的参考代码,您会发现大量警告 - 例如,GetEnumerator&lt;int&gt; 方法是一个实例方法,但是this 参数实际上是 array(例如 int[]),而不是 SZArrayHelper

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 2011-04-05
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多