source code 中提供的评论对于 IList、IEnumerable 和 ICollection 来说
Note that
T[] : IList<T>
, and we want to ensure that if you useIList<YourValueType>
, we ensure aYourValueType[]
can be used without jitting. Hence theTypeDependencyAttribute
onSZArrayHelper
. This is a special hack internally though - see VM\compile.cpp.
为什么 IList<T>
包含对 SZArrayHelper
的依赖?。我明白 SZArrayHelper
是围绕实现 IList<T>
的数组的 CLR 包装器界面,但我不明白为什么这两者会联系在一起。
它如何确保YourValueType[]
不用jitting就可以用吗?
最佳答案
正如您的引述中所述,这是 JIT 中的一个 hack。当 VM 发现有一个 TypeDependency
在 SZArrayHelper
, 它以不同的方式对待类,允许使用更高效的代码。
查看 VM 中的相关代码(请注意,我在这里使用的是较旧的公共(public)版本 - 而不是 实际 .NET VM):
A call to an array thru IList (or IEnumerable or ICollection) has to be handled specially. These interfaces are "magic" (mostly due to working set concerned - they are created on demand internally even though semantically, these are static interfaces.)
首先,数组在 .NET 中有点像 hack。添加通用接口(interface)时,这会带来一些问题 - 例如,int[]
是一个 Array
, 但它也是一种特殊类型,并且是 int 数组;这允许在添加真正的通用类型之前数组是通用的。
现在,让我们看一个具体的例子。你有一个 int[]
,并且您想在 LINQ 中使用它。自 int[]
工具 IEnumerable<int>
,它为您提供了开箱即用的 LINQ 的全部功能,您可以这样写:
var positiveNumbers = numbers.Where(i => i > 0);
从C#的角度来看,没有问题。但是,从 VM 的内部结构来看,这 是个大问题,因为 int[]
实际上没有实现IEnumerable<int>
!即使在将泛型引入 .NET(和 C#)之后,数组仍然以旧方式处理。
破解方法是使用 SZArrayHelper
处理任何这些通用方法。因此,例如 Where
电话 GetEnumerator
在内部 IEnumerable<int>
. VM 发现您正在尝试调用 GetEnumerator
在数组上,而不是虚拟调度 GetEnumerator
在数组实例上,它将调用重定向到 SZArrayHelper.GetEnumerator<int>()
.
这是一个巨大的 hack - 如果您查看 SZArrayHelper
的引用代码,您会发现大量警告 - 例如,GetEnumerator<int>
method 是一个实例方法,但它是 this
参数实际上是数组(例如int[]
),而不是SZArrayHelper
.
但它允许我们将数组视为它们确实实现了所有这些通用接口(interface)——即使它们没有:)
关于c# - IList<T>、IEnumerable<T> 和 ICollection<T> 的 TypeDependencyAttribute ("System.SZArrayHelper"的用途?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33632073/