为什么C#Arrays使用Enumeration的引用类型,但List< T>

Why do C# Arrays use a reference type for Enumeration, but List<T> uses a mutable struct?

根据我读到的内容,出于性能原因,对某些集合的枚举器类型作出了设计决策,将其作为可变结构而不是引用类型。枚举器是最有名的。

我正在研究一些使用数组的旧代码,并惊讶地发现C数组返回szGenericArrayEnumerator类型作为其泛型枚举器类型,这是一种引用类型。

我想知道是否有人知道为什么当许多其他性能关键的集合使用可变结构时,数组的泛型迭代器被实现为引用类型。


From what I've read, a design decision was made for certain Collections's Enumerator Types to be mutable structs instead of reference types for performance reasons.

好问题。

首先,你是对的。虽然一般来说,可变值类型是一种糟糕的代码味道,但在这种情况下,它们是合理的:

  • 变异几乎完全被用户隐藏。
  • 任何人都不太可能以令人困惑的方式使用枚举器。
  • 使用可变值类型实际上解决了非常常见的场景中的实际性能问题。

I am wondering if anyone knows why Array's generic iterator was implemented as a reference type when so many other performance critical collections used mutable structs instead.

因为如果您是那种关心数组枚举性能的人,那么为什么首先使用枚举器呢?它是一个数组,看在上帝的份上;只需编写一个for循环,它像普通人一样重复其指示,从不分配枚举器。(或者一个foreach循环;如果C编译器知道循环集合是一个数组,它会将foreach循环重写为等效的for循环。)

首先,从数组中获取枚举器的唯一原因是,如果要将它传递给一个采用IEnumerator的方法,在这种情况下,如果枚举器是一个结构,那么无论如何都要对它进行装箱。为什么要承担制作值类型然后装箱的费用?只需将其作为引用类型开始。


数组在C编译器中得到一些特殊的处理。当在它们上使用foreach时,编译器将其转换为for循环。因此,使用struct枚举器没有性能优势。

另一方面,List是一个没有任何特殊处理的普通类,因此使用结构可以获得更好的性能。