Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code after yield return is executed

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?

like image 555
helb Avatar asked Feb 27 '14 09:02

helb


People also ask

Is code after yield executed?

It is used to indicate that a function is ready to submit a value. Code is written after the yield statement in the next function call is executed. Code introduced after the return statement will not be executed; instead, it will be ignored. It has the ability to run many times.

When using yield return in a method What should the methods return type be?

The yield return statement returns one element at a time. The return type of yield keyword is either IEnumerable or IEnumerator . The yield break statement is used to end the iteration. We can consume the iterator method that contains a yield return statement either by using foreach loop or LINQ query.

How does yield return work?

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.

Does yield break return null?

"yield break" breaks the Coroutine (it's similar as "return"). "yield return null" means that Unity will wait the next frame to finish the current scope. "yield return new" is similar to "yield return null" but this is used to call another coroutine.


1 Answers

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".

like image 133
dcastro Avatar answered Sep 28 '22 01:09

dcastro