C# Yield return and Its Use

This article is about the C# Yield return key phase and its use.

The Yield return key phase in C# is quite old. It was introduced in C# 2.0. But at that time I was quite new to C# and indeed was not writing any articls. The C# yield key phase always fascinates me and I always wanted to write an article about this mighty key phase.

The Yield return key phase maintains the state machine for a specific collection. Maintains a state machine? But how? What the CLR does is that wherever it sees a yield return key phase being used, the CLR implements an Enumerator pattern for that piece of code. This type of implementation helps the developer from all the types of plumbing that we would have otherwise done in the absence of the keyword. Suppose the developer is filtering a collection, iterating though the collection and then extracting those objects in some new collection. This kind of plumbing is quite monotonous.

As said earlier in this article, yield is not a keyword, in other words it can still be used as a variable. However yield return and yield break are key phrases. Every time the compiler executes a yield return, the generated code will return that value followed by the phase. What happens is that the compiler generates an enumerator that adds the WhileMoveNext return-current plumbing without loosing the memory from the stack. In other words, as long as there are more and more items the stack memory for that collection is kept intact. When the last item is hit, the MoveNext returns false and the stack is unbound and finally the block is executed. The function that uses the Yield return phase returns an IEnumerable<T> type. In other words, there is no need to write the same logic for various types and that again prevents type safe-plumbing.

This article shows how to use the yield return phase to get the list of all the prime numbers between some range of integers while still keeping my application responsive. If I would not have used the yield return phase in that case I could have used a new collection in the method and waited for that method to complete its operation and return the entire collection of prime numbers in one go. Though whatever code I have written here is to display the capability of the yield return phase. I am sure this functionality can be done in a much better way.

In my demo project I have used a function as shown below that uses the yield keyword phase:

  1. static IEnumerable<int> GetPrimes(int from, int to)  
  2. {  
  3.    for (int i = from; i <= to; i++)  
  4.    {  
  5.       if (!_worker.CancellationPending)  
  6.       {  
  7.          bool isPrime = true;  
  8.          int limit = (int)Math.Sqrt(i);  
  9.          for (int j = 2; j <= limit; j++)  
  10.          if (i % j == 0)  
  11.          {  
  12.             isPrime = false;  
  13.             break;  
  14.          }  
  15.          if (isPrime)  
  16.          {  
  17.             yield return i;  
  18.          }  
  19.       }  
  20.    }  

In the preceding code snippet we can see that as soon as the execution finds a prime number the function returns that prime number, remembering the state of the collection from which it returned. While the collection keeps returning values the ListBox keeps updating itself with the values received from the collection that helps us to not wait for the entire result in one go. Try giving a bigger range like 1 to 10000 and you will be able to see the desired result.

The following are some of the basic rules that we should keep in mind while using yield return:
  1. Yield return should only return the expression whose type should be the type of iterator.
  2. Yield return should be inside an iterator block and the iterator block can be in a method body, operator function or property.
  3. Yield statement cannot appear in anonymous methods.
Kindly share your thought about the article.