Why do we need iterators in c#?

前端 未结 10 1915
情话喂你
情话喂你 2021-02-05 18:35

Can somebody provide a real life example regarding use of iterators. I tried searching google but was not satisfied with the answers.

相关标签:
10条回答
  • 2021-02-05 19:09

    Iterators are an abstraction that decouples the concept of position in a collection from the collection itself. The iterator is a separate object storing the necessary state to locate an item in the collection and move to the next item in the collection. I have seen collections that kept that state inside the collection (i.e. a current position), but it is often better to move that state to an external object. Among other things it enables you to have multiple iterators iterating the same collection.

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

    An iterator is an easy way of implementing the IEnumerator interface. Instead of making a class that has the methods and properties required for the interface, you just make a method that returns the values one by one and the compiler creates a class with the methods and properties needed to implement the interface.

    If you for example have a large list of numbers, and you want to return a collection where each number is multiplied by two, you can make an iterator that returns the numbers instead of creating a copy of the list in memory:

    public IEnumerable<int> GetDouble() {
       foreach (int n in originalList) yield return n * 2;
    }
    

    In C# 3 you can do something quite similar using extension methods and lambda expressions:

    originalList.Select(n => n * 2)
    

    Or using LINQ:

    from n in originalList select n * 2
    
    0 讨论(0)
  • 2021-02-05 19:10

    You've probably heard of arrays and containers - objects that store a list of other objects.

    But in order for an object to represent a list, it doesn't actually have to "store" the list. All it has to do is provide you with methods or properties that allow you to obtain the items of the list.

    In the .NET framework, the interface IEnumerable is all an object has to support to be considered a "list" in that sense.

    To simplify it a little (leaving out some historical baggage):

    public interface IEnumerable<T>
    {
        IEnumerator<T> GetEnumerator();
    }
    

    So you can get an enumerator from it. That interface (again, simplifying slightly to remove distracting noise):

    public interface IEnumerator<T>
    {
        bool MoveNext();
        T Current { get; }
    }
    

    So to loop through a list, you'd do this:

    var e = list.GetEnumerator();
    while (e.MoveNext())
    {
        var item = e.Current;
    
        // blah
    }
    

    This pattern is captured neatly by the foreach keyword:

    foreach (var item in list)
        // blah
    

    But what about creating a new kind of list? Yes, we can just use List<T> and fill it up with items. But what if we want to discover the items "on the fly" as they are requested? There is an advantage to this, which is that the client can abandon the iteration after the first three items, and they don't have to "pay the cost" of generating the whole list.

    To implement this kind of lazy list by hand would be troublesome. We would have to write two classes, one to represent the list by implementing IEnumerable<T>, and the other to represent an active enumeration operation by implementing IEnumerator<T>.

    Iterator methods do all the hard work for us. We just write:

    IEnumerable<int> GetNumbers(int stop)
    {
        for (int n = 0; n < stop; n++)
            yield return n;
    }
    

    And the compiler converts this into two classes for us. Calling the method is equivalent to constructing an object of the class that represents the list.

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

    Simple example : a function that generates a sequence of integers :

    static IEnumerable<int> GetSequence(int fromValue, int toValue)
    {
        if (toValue >= fromValue)
        {
            for (int i = fromValue; i <= toValue; i++)
            {
                yield return i;
            }
        }
        else
        {
            for (int i = fromValue; i >= toValue; i--)
            {
                yield return i;
            }
        }
    }
    

    To do it without an iterator, you would need to create an array then enumerate it...

    0 讨论(0)
  • 2021-02-05 19:12
    IEnumerator<Question> myIterator = listOfStackOverFlowQuestions.GetEnumerator();
    while (myIterator.MoveNext())
    {
      Question q;
      q = myIterator.Current;
      if (q.Pertinent == true)
         PublishQuestion(q);
      else
         SendMessage(q.Author.EmailAddress, "Your question has been rejected");
    }
    
    
    foreach (Question q in listOfStackOverFlowQuestions)
    {
        if (q.Pertinent == true)
            PublishQuestion(q);
        else    
            SendMessage(q.Author.EmailAddress, "Your question has been rejected");
    }
    
    0 讨论(0)
  • 2021-02-05 19:14

    A couple of things they're great for:
    a) For 'perceived performance' while maintaining code tidiness - the iteration of something separated from other processing logic.
    b) When the number of items you're going to iterate through is not known.

    Although both can be done through other means, with iterators the code can be made nicer and tidier as someone calling the iterator don't need to worry about how it finds the stuff to iterate through...

    Real life example: enumerating directories and files, and finding the first [n] that fulfill some criteria, e.g. a file containing a certain string or sequence etc...

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