Tuesday, July 19, 2011

The Yield Statement in C#

Yield return statement. Semantically, the yield return statement is equivalent to a return statement (which passes control flow to the calling method), followed by a 'goto' to the yield statement in the next iteration of the foreach loop. This behavior does not exist in the Common Language Runtime, but is rather implemented by a class generated by the C# compiler, which is then executed and JIT-compiled by the CLR.

Another often overlooked C# statement that was introduced in .NET 2.0 is yield. This keyword is used to return items from a loop within a method and retain the state of the method through multiple calls. That is a bit hard to wrap your head around, so as always, an example will help;

public static IEnumerable<int> Range( int min, int max )
{
   for ( int i = min; i < max; i++ )
   {
      yield return i;
   }
}

Each time Range is called, it will return one value in the given range. Of interest is that it maintains the state between calls. The best way to think of it is that for the first call to the method, execution starts at the first line and continues until it hits a yield statement at which time it returns the value. The subsequent runs through the method continue execution at the statement after the yield, continuing to yield values or exiting at the end of the method.
Using this, you can write the following code;

foreach ( int i in Range( 10, 20 ) )
{
   Console.Write( i.ToString() + " " );
}

Which will return the following;
10 11 12 13 14 15 16 17 18 19

Example 2:

 static void Main()
{
// Compute two with the exponent of 10.
foreach (int value in ComputePower(2, 10))
{
    Console.Write(value);
    Console.Write(" ");
}
Console.WriteLine();
    }

    public static IEnumerable<int> ComputePower(int number, int exponent)
    {
int exponentNum = 0;
int numberResult = 1;
//
// Continue loop until the exponent count is reached.
//

while (exponentNum < exponent)
{
   
//
    // Multiply the result.
    //

    numberResult *= number;
    exponentNum++;
   
//
    // Return the result with yield.
    //

    yield return numberResult;
}

}

Output:
2 4 8 16 32 64 128 256 512 1024

FYI

The yield is usually used in Enumerator.

No comments:

Post a Comment