The Yield Statement in C#

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;

<span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">static</span> <span style="color: rgb(43,145,175)">IEnumerable</span><span style="color: rgb(255,0,0)">&lt;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(255,0,0)">&gt;</span> Range( <span style="color: rgb(0,0,255)">int</span> min, <span style="color: rgb(0,0,255)">int</span> max )
{
   <span style="color: rgb(0,0,255)">for</span> ( <span style="color: rgb(0,0,255)">int</span> i <span style="color: rgb(255,0,0)">=</span> min; i <span style="color: rgb(255,0,0)">&lt;</span> max; i<span style="color: rgb(255,0,0)">++</span> )
   {
      <span style="color: rgb(0,0,255)">yield</span> <span style="color: rgb(0,0,255)">return</span> 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;

<span style="color: rgb(0,0,255)">foreach</span> ( <span style="color: rgb(0,0,255)">int</span> i <span style="color: rgb(0,0,255)">in</span> Range( <span style="color: rgb(128,0,128)">10</span>, <span style="color: rgb(128,0,128)">20</span> ) )
{
   <span style="color: rgb(43,145,175)">Console</span><span style="color: rgb(255,0,0)">.</span>Write( i<span style="color: rgb(255,0,0)">.</span>ToString() <span style="color: rgb(255,0,0)">+</span> <span style="color: rgb(163,21,21)">" "</span> );
}

Which will return the following;

10 11 12 13 14 15 16 17 18 19

Why bother you say? Why not just iterate through the numbers yourself? The answer lies in the fact that each call maintains state, so you don’t have to. The above example doesn’t really show you the power, so let’s try a more complex example, calculating prime numbers.

<span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">static</span> <span style="color: rgb(43,145,175)">IEnumerable</span><span style="color: rgb(255,0,0)">&lt;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(255,0,0)">&gt;</span> Primes( <span style="color: rgb(0,0,255)">int</span> max )
{
   <span style="color: rgb(0,0,255)">yield</span> <span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(128,0,128)">2</span>;
   <span style="color: rgb(43,145,175)">List</span><span style="color: rgb(255,0,0)">&lt;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(255,0,0)">&gt;</span> found <span style="color: rgb(255,0,0)">=</span> <span style="color: rgb(0,0,255)">new</span> <span style="color: rgb(43,145,175)">List</span><span style="color: rgb(255,0,0)">&lt;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(255,0,0)">&gt;</span>();
   found<span style="color: rgb(255,0,0)">.</span>Add( <span style="color: rgb(128,0,128)">3</span> );
   <span style="color: rgb(0,0,255)">int</span> candidate <span style="color: rgb(255,0,0)">=</span> <span style="color: rgb(128,0,128)">3</span>;
   <span style="color: rgb(0,0,255)">while</span> ( candidate <span style="color: rgb(255,0,0)">&lt;=</span> max )
   {
      <span style="color: rgb(0,0,255)">bool</span> isPrime <span style="color: rgb(255,0,0)">=</span> <span style="color: rgb(0,0,255)">true</span>;
      <span style="color: rgb(0,0,255)">foreach</span> ( <span style="color: rgb(0,0,255)">int</span> prime <span style="color: rgb(0,0,255)">in</span> found )
      {
         <span style="color: rgb(0,0,255)">if</span> ( prime <span style="color: rgb(255,0,0)">*</span> prime <span style="color: rgb(255,0,0)">&gt;</span> candidate )
         {
            <span style="color: rgb(0,0,255)">break</span>;
         }
         <span style="color: rgb(0,0,255)">if</span> ( candidate <span style="color: rgb(255,0,0)">%</span> prime <span style="color: rgb(255,0,0)">==</span> <span style="color: rgb(128,0,128)">0</span> )
         {
            isPrime <span style="color: rgb(255,0,0)">=</span> <span style="color: rgb(0,0,255)">false</span>;
            <span style="color: rgb(0,0,255)">break</span>;
         }
      }
      <span style="color: rgb(0,0,255)">if</span> ( isPrime )
      {
         found<span style="color: rgb(255,0,0)">.</span>Add( candidate );
         <span style="color: rgb(0,0,255)">yield</span> <span style="color: rgb(0,0,255)">return</span> candidate;
      }
      candidate <span style="color: rgb(255,0,0)">+=</span> <span style="color: rgb(128,0,128)">2</span>;
   }
}

Notice that there are multiple yields within this method and that the state is maintained through each call. You can now print out all of the prime numbers below 50 with;

<span style="color: rgb(0,0,255)">foreach</span> ( <span style="color: rgb(0,0,255)">int</span> prime <span style="color: rgb(0,0,255)">in</span> Primes( <span style="color: rgb(128,0,128)">50</span> ) )
{
   <span style="color: rgb(43,145,175)">Console</span><span style="color: rgb(255,0,0)">.</span>Write( prime<span style="color: rgb(255,0,0)">.</span>ToString() <span style="color: rgb(255,0,0)">+</span> <span style="color: rgb(163,21,21)">" "</span> );
}

There is also the yield break statement. If a yield break statement is hit within a method, execution of that method stops with no return. Using this, the first method could be rewritten like this;

<span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">static</span> <span style="color: rgb(43,145,175)">IEnumerable</span><span style="color: rgb(255,0,0)">&lt;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(255,0,0)">&gt;</span> Range( <span style="color: rgb(0,0,255)">int</span> min, <span style="color: rgb(0,0,255)">int</span> max )
{
   <span style="color: rgb(0,0,255)">while</span> ( <span style="color: rgb(0,0,255)">true</span> )
   {
      <span style="color: rgb(0,0,255)">if</span> ( min <span style="color: rgb(255,0,0)">&gt;=</span> max )
      {
         <span style="color: rgb(0,0,255)">yield</span> <span style="color: rgb(0,0,255)">break</span>;
      }
      <span style="color: rgb(0,0,255)">yield</span> <span style="color: rgb(0,0,255)">return</span> min<span style="color: rgb(255,0,0)">++</span>;
   }
}

It is not as useful in this case, but I’ll leave it to you to find more interesting reasons to break out of a loop. Also, even though I used the generic IEnumerable<T> for all of my examples, you can also use IEnumerable.

8 thoughts on “The Yield Statement in C#

  1. Is the yield threadsafe? What happens when you have 2 threads hitting the same static method? Is the state maintained for each separate thread?

  2. One key point to add is that execution of yield methods are deferred: they aren’t evaluated until you foreach over them. Thus, the following code, even though it looks like an infinite loop, is perfectly fine:

    while(true)
    {
    yield return 1;
    }

    It will simply keep yielding 1 until you stop foreach-ing over it.

    Another point to consider is that since yield methods are delay-executed, any argument validation won’t get applied until you foreach over it. For example,

    IEnumerable GetEvens(IEnumerable input)
    {
    if (input == null ) throw new ArgumentNullException();

    yield return …;
    }

    Calling that method like this:
    IEnumerable evens = GetEvents(null);

    It won’t result in an exception! Not until you foreach over evens.

    For this reason, argument validation should be done first, then return the result of another method that does the actual yielding.

Comments are closed.