Consider the following example:
class YieldTest
{
static void Main(string[] args)
{
var res = Create(new string[] { "1 12 123", "1234", "12345" });
}
static IEnumerable<int> Create(IEnumerable<string> strings)
{
foreach(string s in strings)
{
yield return s.Length;
if(s.Contains(' '))
{
string[] tokens = s.Split(' ');
foreach(string t in tokens)
{
yield return t.Length;
}
}
}
}
}
The call to Create
returns {8, 1, 2, 3, 4, 5}.
What really confuses me is that the code after the yield return statement is executed.
(Why would they name it yield return
and not just yield
??)
The documentation tells us
When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained.
What does that mean? Where does a return occur? What is an iterator method?
It means your code is transformed into a state machine by the compiler.
When you call Create
method, you'll get an IEnumerable<T>
. You can then call GetEnumerator()
on it and obtain an IEnumerator<T>
.
Now, every time you call MoveNext
on this iterator, your code will execute until it finds the first yield
statement (whether it be yield return
or yield break
).
If it hits a yield return x
, MoveNext
returns true and the iterator's Current
property will be set to x
, and the rest of the code will be executed the next time you call MoveNext
.
This happens until either there's no more code to run or the code hits a yield break
. At that point, MoveNext
will return false.
yield return 1;
yield return 2;
yield return 3;
Calling MoveNext
on this piece of code will return true the first three times, and at each iteration, Current
will be set to 1, 2 and 3.
Edit 2:
Regarding the yield return ??
syntax, from Eric Lippert's Ambiguous Optional Parentheses, Part Three
When they designed C# 2.0 they had this problem:
yield(x);
Does that mean "yield x in an iterator" or "call the yield method with argument x?" By changing it to
yield return(x);
it is now unambiguous; it cannot possibly mean "call the yield method".