Enumerator Implementation: Use struct or class?

前端 未结 8 2647
再見小時候
再見小時候 2021-02-19 17:44

I noticed that List defines its enumerator as a struct, while ArrayList defines its enumerator as a class. What\'s t

相关标签:
8条回答
  • 2021-02-19 17:55

    An enumerator is inherently a changing structure, since it needs to update internal state to move on to the next value in the original collection.

    In my opinion, structs should be immutable, so I would use a class.

    0 讨论(0)
  • 2021-02-19 17:58

    Reason List uses a struct enumerator is to prevent garbage generation in foreach statements. This is pretty good reason especially if you are programming for Compact Framework, because CF doesn't have generational GC and CF is usually used on low performance hardware where it can quickly lead to performance issues.

    Also, I don't think mutable structs are source of problems in examples some posted, but programmers that don't have good understanding of how value types work.

    0 讨论(0)
  • 2021-02-19 18:09

    Like this others, I would choose a class. Mutable structs are nasty. (And as Jared suggests, I'd use an iterator block. Hand-coding an enumerator is fiddly to get right.)

    See this thread for an example of the list enumerator being a mutable struct causing problems...

    0 讨论(0)
  • 2021-02-19 18:10

    There's a couple of blog posts that cover exactly this issue. Basically, enumerator structs are a really really bad idea...

    0 讨论(0)
  • 2021-02-19 18:13

    Any implementation of IEnumerable<T> should return a class. It may be useful for performance reasons to have a GetEnumerator method which returns a struct which provides the methods necessary for enumeration but does not implement IEnumerator<T>; this method should be different from IEnumerable<T>.GetEnumerator, which should then be implemented explicitly.

    Using this approach will allow for enhanced performance when the class is enumerated using a foreach or "For Each" loop in C# or vb.net or any context where the code which is doing the enumeration will know that the enumerator is a struct, but avoid the pitfalls that would otherwise occur when the enumerator gets boxed and passed by value.

    0 讨论(0)
  • 2021-02-19 18:17

    To expand on @Earwicker: you're usually better off not writing an enumerator type, and instead using yield return to have the compiler write it for you. This is because there are a number of important subtleties that you might miss if you do it yourself.

    See SO question "What is the yield keyword used for in C#?" for some more details on how to use it.

    Also Raymond Chen has a series of blog posts ("The implementation of iterators in C# and its consequences": parts 1, 2, 3, and 4) that show you how to implement an iterator properly without yield return, which shows just how complex it is, and why you should just use yield return.

    0 讨论(0)
提交回复
热议问题