在.NET中,Array只扩展IEnumerable,所以当foreach循环通过值类型数组时会有装箱和拆箱吗?

Cui*_*崔鹏飞 4 .net arrays generics foreach value-type

Array只扩展了IEnumerable的非泛型版本,当foreach循环通过值类型数组时,是否会有装箱和拆箱?

我猜不是,因为那会很蹩脚.如果我的猜测是正确的,那么foreach如何通过值类型数组?它不使用Array.GetEnumerator方法吗?如果没有,为什么Array扩展IEnumerable?

谢谢

Cod*_*aos 6

Array在运行时有很多特殊的外壳.特别是它是伪通用的.即如果你指定一个具体的数组类型,如T[]实现泛型集合接口,如IEnumerable<T>.

如果我没记错的话,它甚至foreach通过GetEnumerator返回具有强类型的具体类型来支持非仿制迭代Current.这样做起因为foreach不需要IEnumerator/ IEnumerableinterfaces,但也适用于正确命名的成员.

所以你可以在foreach没有装箱的情况下迭代数组.

  • 它被使用,它是在许多代码中特殊的,如foreach-loops,编译器注意到你给它一个数组.但是,如果你在一个采用IEnumerable的方法中,它将不知道,然后它是必需的. (2认同)

pho*_*oog 5

CodesInChaos 的答案是不正确的。由于 C# 编译器中的特殊处理(而不是运行时中的特殊处理),值类型数组的迭代无需装箱。当迭代集合的静态类型是数组类型时,C# 编译器会将 foreach 循环转换为 for 循环。

另外,您的问题基于错误的假设(“数组仅扩展 IEnumerable 的非通用版本”)。事实上,数组实现了通用的IEnumerable<T>; 只是出于向后兼容性的原因,这是使用显式成员实现来完成的。(此外,数组实现通用接口的事实System.Array运行时特殊处理的情况;反编译 mscorlib 时,您不会在定义中看到它们。)

这意味着如果您有一个 array int[] a,并且您调用a.GetEnumerator(),您将获得一个非泛型IEnumerator引用。但是,您可以显式转换以获得通用IEnumerator<int>引用:((IEnumerable<int>)a).GetEnumerator()