What is the purpose/advantage of using yield return iterators in C#?

前端 未结 10 1792
独厮守ぢ
独厮守ぢ 2020-12-04 06:43

All of the examples I\'ve seen of using yield return x; inside a C# method could be done in the same way by just returning the whole list. In those cases, is th

相关标签:
10条回答
  • 2020-12-04 07:18

    If the entire list is gigantic, it might eat a lot of memory just to sit around, whereas with the yield you only play with what you need, when you need it, regardless of how many items there are.

    0 讨论(0)
  • 2020-12-04 07:20

    Using the yield return you can iterate over items without ever having to build a list. If you don't need the list, but want to iterate over some set of items it can be easier to write

    foreach (var foo in GetSomeFoos()) {
        operate on foo
    }
    

    Than

    foreach (var foo in AllFoos) {
        if (some case where we do want to operate on foo) {
            operate on foo
        } else if (another case) {
            operate on foo
        }
    }
    

    You can put all of the logic for determining whether or not you want to operate on foo inside your method using yield returns and you foreach loop can be much more concise.

    0 讨论(0)
  • 2020-12-04 07:23

    In toy/demonstration scenarios, there isn't a lot of difference. But there are situations where yielding iterators are useful - sometimes, the entire list isn't available (e.g. streams), or the list is computationally expensive and unlikely to be needed in its entirety.

    0 讨论(0)
  • 2020-12-04 07:25

    The basic reason for using yield is it generates/returns a list by itself. We can use the returned list for iterating further.

    0 讨论(0)
  • 2020-12-04 07:27

    But what if you were building a collection yourself?

    In general, iterators can be used to lazily generate a sequence of objects. For example Enumerable.Range method does not have any kind of collection internally. It just generates the next number on demand. There are many uses to this lazy sequence generation using a state machine. Most of them are covered under functional programming concepts.

    In my opinion, if you are looking at iterators just as a way to enumerate through a collection (it's just one of the simplest use cases), you're going the wrong way. As I said, iterators are means for returning sequences. The sequence might even be infinite. There would be no way to return a list with infinite length and use the first 100 items. It has to be lazy sometimes. Returning a collection is considerably different from returning a collection generator (which is what an iterator is). It's comparing apples to oranges.

    Hypothetical example:

    static IEnumerable<int> GetPrimeNumbers() {
       for (int num = 2; ; ++num) 
           if (IsPrime(num))
               yield return num;
    }
    
    static void Main() { 
       foreach (var i in GetPrimeNumbers()) 
           if (i < 10000)
               Console.WriteLine(i);
           else
               break;
    }
    

    This example prints prime numbers less than 10000. You can easily change it to print numbers less than a million without touching the prime number generation algorithm at all. In this example, you can't return a list of all prime numbers because the sequence is infinite and the consumer doesn't even know how many items it wants from the start.

    0 讨论(0)
  • 2020-12-04 07:28

    The fine answers here suggest that a benefit of yield return is that you don't need to create a list; Lists can be expensive. (Also, after a while, you'll find them bulky and inelegant.)

    But what if you don't have a List?

    yield return allows you to traverse data structures (not necessarily Lists) in a number of ways. For example, if your object is a Tree, you can traverse the nodes in pre- or post- order without creating other lists or changing the underlying data structure.

    public IEnumerable<T> InOrder()
    {
        foreach (T k in kids)
            foreach (T n in k.InOrder())
                yield return n;
        yield return (T) this;
    }
    
    public IEnumerable<T> PreOrder()
    {
        yield return (T) this;
        foreach (T k in kids)
            foreach (T n in k.PreOrder())
                yield return n;
    }
    
    0 讨论(0)
提交回复
热议问题