Trouble understanding yield in C#

This question already has an answer here:

  • What is the yield keyword used for in C#? 16 answers

  • This is called deferred execution, yield is lazy and will only work as much as it needs to.

    This has great many advantages, one of which being that you can create seemingly infinite enumerations:

    public IEnumerable<int> InfiniteOnes()
    {
         while (true)
             yield 1;
    }
    

    Now imagine that the following:

    var infiniteOnes = InfiniteOnes();
    

    Would execute eagerly, you'd have a StackOverflow exception coming your way quite happily.

    On the other hand, because its lazy, you can do the following:

    var infiniteOnes = InfiniteOnes();
    //.... some code
    foreach (var one in infiniteOnes.Take(100)) { ... }
    

    And later,

    foreach (var one in infiniteOnes.Take(10000)) { ... }
    

    Iterator blocks will run only when they need to; when the enumeration is iterated, not before, not after.


    From msdn:

    Deferred Execution

    Deferred execution means that the evaluation of an expression is delayed until its realized value is actually required. Deferred execution can greatly improve performance when you have to manipulate large data collections, especially in programs that contain a series of chained queries or manipulations. In the best case, deferred execution enables only a single iteration through the source collection.

    Deferred execution is supported directly in the C# language by the yield keyword (in the form of the yield-return statement) when used within an iterator block. Such an iterator must return a collection of type IEnumerator or IEnumerator<T> (or a derived type).

    var vendorIterator = repository.RetrieveWithIterator(); // <-- Lets deferred the execution
    foreach (var item in vendorIterator) // <-- execute it because we need it
    {
        Debug.WriteLine(item);
    }
    var actual = vendorIterator.ToList();
    

    Eager vs. Lazy Evaluation

    When you write a method that implements deferred execution, you also have to decide whether to implement the method using lazy evaluation or eager evaluation.

  • In lazy evaluation, a single element of the source collection is processed during each call to the iterator. This is the typical way in which iterators are implemented.
  • In eager evaluation, the first call to the iterator will result in the entire collection being processed. A temporary copy of the source collection might also be required.
  • Lazy evaluation usually yields better performance because it distributes overhead processing evenly throughout the evaluation of the collection and minimizes the use of temporary data. Of course, for some operations, there is no other option than to materialize intermediate results.

    source


    It will get the items when you loop over them when needed. This way say you only need the first 4 results and then you break, it won't yield anything more and you just saved some processing power!

    From MS Docs:

    You use a yield return statement to return each element one at a time. You consume an iterator method by using a foreach statement or LINQ query. Each iteration of the foreach loop calls the iterator method. When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained. Execution is restarted from that location the next time that the iterator function is called. You can use a yield break statement to end the iteration.

    Note - If you .ToList() on the result of a method that yields, it will work as if you returned a single list, thus defeating the purpose of yield.

    链接地址: http://www.djcxy.com/p/9090.html

    上一篇: Yield关键字的确切用法是什么?

    下一篇: 在C#中理解产量问题