Trouble understanding yield in C#
This question already has an answer here:
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.
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.
上一篇: Yield关键字的确切用法是什么?
下一篇: 在C#中理解产量问题