Distinction between iterator and enumerator

2019-01-16 02:22发布

An interview question for a .NET 3.5 job is "What is the difference between an iterator and an enumerator"?

This is a core distinction to make, what with LINQ, etc.

Anyway, what is the difference? I can't seem to find a solid definition on the net. Make no mistake, I can find the meaning of the two terms but I get slightly different answers. What would be the best answer for an interview?

IMO an iterator "iterates" over a collection, and an enumerator provides the functionality to iterate, but this has to be called.

Also, using the yield keyword is said to save state. What exactly is this state? Is there an example of this benefit occurring?

8条回答
叛逆
2楼-- · 2019-01-16 02:35

"Iterators are a new feature in C# 2.0. An iterator is a method, get accessor or operator that enables you to support foreach iteration in a class or struct without having to implement the entire IEnumerable interface. Instead, you provide just an iterator, which simply traverses the data structures in your class. When the compiler detects your iterator, it will automatically generate the Current, MoveNext and Dispose methods of the IEnumerable or IEnumerable interface." - msdn

查看更多
贼婆χ
3楼-- · 2019-01-16 02:37

Enumeration deals with objects while iteration deals with values only. Enumeration is used when we use vector hashtable etc while iteration are used in while loop for loop etc. I've never use the yield keyword so I couldn't tell you.

查看更多
爷的心禁止访问
4楼-- · 2019-01-16 02:39

Since no examples were given, here is one that was helpful to me.

An enumerator is an object that you get when you call .GetEnumerator() on a class or type that implements the IEnumerator interface. When this interface is implemented, you have created all the code necessary for the compilor to enable you to use foreach to "iterate" over your collection.

Don't get that word 'iterate" confused with iterator though. Both the Enumerator and the iterator allow you to "iterate". Enumerating and iterating are basically the same process, but are implemented differently. Enumerating means you've impleneted the IEnumerator interface. Iterating means you've created the iterator construct in your class (demonstrated below), and you are calling foreach on your class, at which time the compilor automatically creates the enumerator functionality for you.

Also note that you don't have to do squat with your enumerator. You can call MyClass.GetEnumerator() all day long, and do nothing with it (example:

IEnumerator myEnumeratorThatIWillDoNothingWith = MyClass.GetEnumerator()).

Note too that your iterator construct in your class only realy gets used when you are actually using it, i.e. you've called foreach on your class.

Here is an iterator example from msdn:

public class DaysOfTheWeek : System.Collections.IEnumerable
{

     string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

     //This is the iterator!!!
     public System.Collections.IEnumerator GetEnumerator()
     {
         for (int i = 0; i < days.Length; i++)
         {
             yield return days[i];
         }
     }

}

class TestDaysOfTheWeek
{
    static void Main()
    {
        // Create an instance of the collection class
        DaysOfTheWeek week = new DaysOfTheWeek();

        // Iterate with foreach - this is using the iterator!!! When the compiler
        //detects your iterator, it will automatically generate the Current, 
        //MoveNext and Dispose methods of the IEnumerator or IEnumerator<T> interface
        foreach (string day in week)
        {
            System.Console.Write(day + " ");
        }
    }
}
// Output: Sun Mon Tue Wed Thr Fri Sat
查看更多
小情绪 Triste *
5楼-- · 2019-01-16 02:41

In C# 2+, iterators are a way for the compiler to automatically generate the IEnumerable and/or IEnumerable<T> interfaces for you.

Without iterators, you would need to create a class implementing IEnumerator, including Current, MoveNext, and Reset. This requires a fair amount of work. Normally, you would create a private class that implemtented IEnumerator<T> for your type, then yourClass.GetEnumerator() would construct that private class, and return it.

Iterators are a way for the compiler to automatically generate this for you, using a simple syntax (yield). This lets you implement GetEnumerator() directly in your class, without a second class (The IEnumerator) being specified by you. The construction of that class, with all of its members, is done for you.

Iterators are very developer friendly - things are done in a very efficient way, with much less effort.

When you use foreach, the two will behave identically (provided you write your custom IEnumerator correctly). Iterators just make life much simpler.

查看更多
手持菜刀,她持情操
6楼-- · 2019-01-16 02:47

"Whereas a foreach statement is the consumer of the enumerator, an iterator is the producer of the enumerator."

The above is how "C# 5.0 In A NutShell" explains it, and has been helpful for me.

In other words, the foreach statement uses MoveNext(), and the Current property of the IEnumerator to iterate through a sequence, while the iterator is used to produce the implementation of the IEnumerator that will be used by the foreach statement. In C#, when you write an iterator method containing a yield statement, the compiler will generate a private enumerator for you. And when you iterate through the items in the sequence, it will call the MoveNext() and Current property of the private enumerator. These methods/properties are implemented by your code in the iterator method that will be called repeately to yield values until there are not values left to yield.

This is my understanding of how C# define enumerators, and iterators.

查看更多
等我变得足够好
7楼-- · 2019-01-16 02:48

Iterating means repeating some steps, while enumerating means going through all values in a collection of values. So enumerating usually requires some form of iteration.

In that way, enumerating is a special case of iterating where the step is getting a value from a collection.

Note the "usually" – enumerating may also be performed recursively, but recursion and iteration are so closely related that I would not care about this small difference.

You may also enumerate values you do not explicitly store in a collection. For example, you can enumerate the natural number, primes, or whatever but you would calculate these values during the enumeration and not retrieve them from a physical collection. You understand this case as enumerating a virtual collection with its values defined by some logic.


I assume Reed Copsey got the point. In C# there are two major ways to enumerate something.

  1. Implement Enumerable and a class implementing IEnumerator
  2. Implement an iterator with the yield statement

The first way is harder to implement and uses objects for enumerating. The second way is easier to implement and uses continuations.

查看更多
登录 后发表回答