为什么 C# 数组使用引用类型进行枚举,而 List使用引用类型?使用可变结构?
根据我的阅读,出于性能原因,我们做出了将某些集合的枚举器类型设置为可变结构而不是引用类型的设计决策。 List.Enumerator 是最著名的。
我正在研究一些使用数组的旧代码,并惊讶地发现 C# 数组返回类型 SZGenericArrayEnumerator 作为其通用枚举器类型,这是一种引用类型。
我想知道是否有人知道为什么 Array 的通用迭代器被实现为引用类型,而许多其他性能关键的集合都使用可变结构。
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. List.Enumerator is the most well known.
I was investigating some old code that used arrays, and was surprised to discover that C# Arrays return the type SZGenericArrayEnumerator as their generic enumerator type, which is a reference type.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好问题。
首先,你是对的。虽然一般来说,可变值类型是一种不好的代码味道,但在这种情况下它们是合理的:
因为如果您是那种关心枚举数组性能的人,那么为什么您首先要使用枚举器?这是一个数组清酒;只需编写一个
for
循环,像普通人一样迭代其索引,并且从不分配枚举器。 (或foreach
循环;如果 C# 编译器知道循环集合是一个数组,则将foreach
循环重写为等效的for
循环。)首先从数组获取枚举器的唯一原因是,如果您将其传递给采用
IEnumerator
的方法,在这种情况下 if那么枚举器是一个结构体无论如何你都会打它。为什么要承担创建值类型然后装箱的费用?首先将其设为引用类型即可。Good question.
First off, you are correct. Though in general, mutable value types are a bad code smell, in this case they are justified:
Because if you're the sort of person who is concerned about the performance of enumerating an array then why are you using an enumerator in the first place? It's an array for heaven's sake; just write a
for
loop that iterates over its indicies like a normal person and never allocate the enumerator. (Or aforeach
loop; the C# compiler will rewrite theforeach
loop into the equivalentfor
loop if it knows that the loop collection is an array.)The only reason why you'd obtain an enumerator from an array in the first place is if you are passing it to a method that takes an
IEnumerator<T>
, in which case if the enumerator is a struct then you're going to be boxing it anyway. Why take on the expense of making the value type and then boxing it? Just make it a reference type to begin with.数组在 C# 编译器中得到一些特殊处理。当您对它们使用
foreach
时,编译器会将其转换为for
循环。因此,使用 struct 枚举器没有任何性能优势。另一方面,
List
是一个普通类,没有任何特殊处理,因此使用结构会带来更好的性能。Arrays get some special treatment in the C# compiler. When you use
foreach
on them, the compiler translates it into afor
loop. So there is no performance benefit in usingstruct
enumerators.List<T>
on the other hand is a plain class without any special treatment, so using a struct results in better performance.