我注意到List<T>
将其枚举器定义为 a struct
,而ArrayList
将其枚举器定义为 a class
。有什么不同?如果我要为我的班级编写一个枚举器,哪个更可取?
编辑:使用无法满足我的要求yield
,因此我正在实现自己的枚举器。也就是说,我想知道是否最好按照List<T>
struct 的方式实现它。
我注意到List<T>
将其枚举器定义为 a struct
,而ArrayList
将其枚举器定义为 a class
。有什么不同?如果我要为我的班级编写一个枚举器,哪个更可取?
编辑:使用无法满足我的要求yield
,因此我正在实现自己的枚举器。也就是说,我想知道是否最好按照List<T>
struct 的方式实现它。
在 C# 中编写枚举器的最简单方法是使用“yield return”模式。例如。
public IEnumerator<int> Example() {
yield return 1;
yield return 2;
}
此模式将在后台生成所有枚举器代码。这使您无法做出决定。
像其他人一样,我会选择一个班级。可变结构很讨厌。(正如 Jared 所建议的,我会使用一个迭代器块。手工编码一个枚举器是很巧妙的。)
有关列表枚举器是导致问题的可变结构的示例,请参见此线程...
原因列表使用结构枚举器是为了防止在 foreach 语句中产生垃圾。这是一个很好的理由,特别是如果您正在为 Compact Framework 编程,因为 CF 没有分代 GC,并且 CF 通常用于低性能硬件,它会很快导致性能问题。
另外,我不认为可变结构是一些发布的示例中问题的根源,但是程序员对值类型的工作方式没有很好的理解。
使用yield return
.
至于为什么您可能会在class
or之间进行选择struct
,如果您将其设置为 a ,struct
那么它会在作为接口返回后立即被装箱,因此将其设置为 astruct
会导致额外的复制发生。看不出这有什么意义!
枚举器本质上是一个不断变化的结构,因为它需要更新内部状态才能移动到原始集合中的下一个值。
在我看来,结构应该是不可变的,所以我会使用一个类。
的任何实现都IEnumerable<T>
应该返回一个类。出于性能原因,拥有一个返回结构体的方法可能很有用,GetEnumerator
该结构体提供枚举所需的方法但不实现IEnumerator<T>
;此方法应不同于IEnumerable<T>.GetEnumerator
,然后应显式实施。
当使用 C# 或 vb.net 中的 foreach 或“For Each”循环或任何执行枚举的代码将知道枚举数是结构的上下文中枚举类时,使用此方法将提高性能,但避免当枚举器被装箱并按值传递时会发生的陷阱。
要扩展@Earwicker:您通常最好不要编写枚举器类型,而是使用yield return
让编译器为您编写它。这是因为如果你自己做,你可能会错过许多重要的细节。
有关如何使用它的更多详细信息,请参阅 SO 问题“ C# 中使用的 yield 关键字是什么? ”。
此外, Raymond Chen有一系列博客文章(“ C#中迭代器的实现及其后果”:第 1、2、3 和 4 部分)向您展示了如何在没有 的情况下正确实现迭代器,这表明它是多么复杂,以及为什么你应该只使用.yield return
yield return