枚举器实现:使用struct还是class?

时间:2008-12-21 14:23:04

标签: c# .net enumeration struct-vs-class

我注意到List<T>将其枚举器定义为struct,而ArrayList将其枚举器定义为class。有什么不同?如果我要为我的班级写一个调查员,哪一个更好?

编辑:使用yield无法满足我的要求,因此我正在实施自己的枚举器。也就是说,我想知道是否更好地遵循List<T>的行并将其作为结构实现。

8 个答案:

答案 0 :(得分:9)

在C#中编写枚举器的最简单方法是使用“yield return”模式。例如。

public IEnumerator<int> Example() {
  yield return 1;
  yield return 2;
}

此模式将生成引擎盖下的所有枚举器代码。这取决于您的决定。

答案 1 :(得分:9)

像其他人一样,我会选择一个班级。可变结构是令人讨厌的。 (正如Jared建议的那样,我会使用一个迭代器块。手动编码一个枚举器很难做到正确。)

有关列表枚举器是导致问题的可变结构的示例,请参阅this thread ...

答案 2 :(得分:7)

Reason List使用struct枚举器是为了防止在foreach语句中生成垃圾。这是非常好的理由,特别是如果您正在为Compact Framework进行编程,因为CF没有分代GC,CF通常用在低性能硬件上,很快就会导致性能问题。

此外,我不认为可变结构是一些发布的示例中的问题的根源,但程序员对价值类型的工作方式不是很了解。

答案 3 :(得分:5)

使用yield return撰写。

至于为什么你可能会在classstruct之间进行选择,如果你将它设为struct,那么只要它作为界面返回就会被装箱,所以制作它struct只会导致进行额外的复制。看不出来的意思!

答案 4 :(得分:5)

枚举器本质上是一个变化的结构,因为它需要更新内部状态以继续前进到原始集合中的下一个值。

在我看来,结构应该是不可变的,所以我会使用一个类。

答案 5 :(得分:2)

IEnumerable<T>的任何实现都应该返回一个类。出于性能原因,使用GetEnumerator方法返回一个结构可能是有用的,该结构提供枚举所需的方法但不实现IEnumerator<T>;此方法应与IEnumerable<T>.GetEnumerator不同,后者应明确实施。

使用此方法可以在使用C#或vb.net中的foreach或“For Each”循环或任何执行枚举的代码将知道枚举器是结构的上下文中枚举类时提高性能,但要避免在枚举器被盒装并按值传递时会发生的陷阱。

答案 6 :(得分:1)

要扩展@Earwicker:你通常最好不要编写枚举器类型,而是使用yield return让编译器为你编写它。这是因为如果你自己做的话,你可能会错过许多重要的细微之处。

有关如何使用它的详细信息,请参阅问题“What is the yield keyword used for in C#?”。

同样Raymond Chen有一系列博文(“The implementation of iterators in C# and its consequences”:部分1234)这将向您展示如何在没有yield return的情况下正确实现迭代器,这显示了它的复杂程度,以及为什么要使用yield return

答案 7 :(得分:1)

有几个blog posts正好涵盖了这个问题。基本上,枚举器结构是一个非常糟糕的主意......