When i have a code block
static void Main()
{
foreach (int i in YieldDemo.SupplyIntegers())
{
Console.WriteLine("{0} is consumed by foreach iteration", i);
}
}
class YieldDemo
{
public static IEnumerable<int> SupplyIntegers()
{
yield return 1;
yield return 2;
yield return 3;
}
}
can i interpret the principle behind yield return as
- Main() calls the SupplyIntegers()
|1| |2| |3| are stored in contiguous memory block.Pointer of "IEnumerator" Moves to |1|- Control returns from SupplyInteger() to Main().
- Main() prints the value
- Pointer Moves to |2|, and so on.
Clarifications :
(1) Normally we will have one valid return statement is allowed inside a function.How does
C# treats when multiple yield return ,yield return,… statements are present?
(2) Once the return is encountered there is no way for control again coming back to
SupplyIntegers(), in case it is allowed won’t the Yield again starts from 1 ? I mean yield return 1?
Nope – far from it; I’ll write a long-hand version for you… it is too grungy!
Note it also helps if you understand that the
foreachis actually:As you can see, it builds a state machine in the iterator, with the state machine progressed by
MoveNext. I’ve used the pattern with astatefield, as you can see how this would work for more complex iterators.Importantly:
finallyblock (includingusing), it goes in theDispose()yield returnbecome acase(roughly)yield breakbecomes astate = -1; return false;(or similar)The way the C# compiler does this is very complicated, but it makes writing iterators a breeze.