Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the compiler use 'yield return' to build a class

Tags:

c#

In specific, if I say:

    public static IEnumerable<String> Data()
    {
        String connectionString = "...";
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            IDataReader reader = new SqlCommand("", connection).ExecuteReader();

            while (reader.Read())
                yield return String.Format("Have a beer {0} {1}!", reader["First_Name"], reader["Last_Name"]);

            connection.Close();
        }
    }

How does the compiler go about generating a concrete enumerable class out of this?

like image 301
sircodesalot Avatar asked Mar 11 '13 17:03

sircodesalot


People also ask

How does yield return work?

yield return is used with enumerators. On each call of yield statement, control is returned to the caller but it ensures that the callee's state is maintained. Due to this, when the caller enumerates the next element, it continues execution in the callee method from statement immediately after the yield statement.

What is the use of yield return in C#?

You use a yield return statement to return each element one at a time. The sequence returned from an iterator method can be consumed by using a foreach statement or LINQ query. Each iteration of the foreach loop calls the iterator method.

What is the use of the yield keyword?

The yield keyword is use to do custom stateful iteration over a collection. The yield keyword tells the compiler that the method in which it appears is an iterator block. yield return <expression>; yield break; The yield return statement returns one element at a time.

What is the use of yield keyword in C# with example?

Using yield to define an iterator removes the need for an explicit extra class (the class that holds the state for an enumeration, see IEnumerator<T> for an example) when you implement the IEnumerable and IEnumerator pattern for a custom collection type. The following example shows the two forms of the yield statement.


1 Answers

It builds a state machine, basically:

  • It creates a private nested class, with instance variables corresponding to the local variables in your method, and a state variable to keep track of where it's got to
  • The state machine implements IEnumerable<T> and IEnumerator<T> - the MoveNext() method gets to the right bit of the logic (based on state) and sets an instance variable to keep track of the last-yielded value (the Current property)
  • The compiler creates a "skeleton" method with the same signature as your original, which creates an instance of the state machine

See my article on the topic for more details. Also note that async/await in C# 5 is built with a lot of the same ideas (although there are various implementation differences).

like image 197
Jon Skeet Avatar answered Nov 15 '22 00:11

Jon Skeet