为什么 C# 数组使用引用类型进行枚举,而 List使用引用类型?使用可变结构?

发布于 2025-01-03 04:41:24 字数 231 浏览 0 评论 0原文

根据我的阅读,出于性能原因,我们做出了将某些集合的枚举器类型设置为可变结构而不是引用类型的设计决策。 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听风吹 2025-01-10 04:41:24

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

好问题。

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

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

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

因为如果您是那种关心枚举数组性能的人,那么为什么您首先要使用枚举器?这是一个数组清酒;只需编写一个 for 循环,像普通人一样迭代其索引,并且从不分配枚举器。 (或 foreach 循环;如果 C# 编译器知道循环集合是一个数组,则将 foreach 循环重写为等效的 for 循环。)

首先从数组获取枚举器的唯一原因是,如果您将其传递给采用 IEnumerator 的方法,在这种情况下 if那么枚举器是一个结构体无论如何你都会打它。为什么要承担创建值类型然后装箱的费用?首先将其设为引用类型即可。

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.

Good question.

First off, you are correct. Though in general, mutable value types are a bad code smell, in this case they are justified:

  • The mutation is almost entirely concealed from the user.
  • It is highly unlikely that anyone is going to use the enumerator in a confusing manner.
  • The use of a mutable value type actually does solve a realistic performance problem in an extremely common scenario.

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.

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 a foreach loop; the C# compiler will rewrite the foreach loop into the equivalent for 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.

旧人 2025-01-10 04:41:24

数组在 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 a for loop. So there is no performance benefit in using struct enumerators.

List<T> on the other hand is a plain class without any special treatment, so using a struct results in better performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文