C# Yield Return and its Use - CodeProject

:

Though 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 blogs. C# yield key phase always fascinates me and I always wanted to write an article about this mighty key phase.

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

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

Here in this article, I want to show you how I have used 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 whole collection of prime numbers at 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 achieved in a much better way.

In my demo project, I have used a function as shown below which uses the yield keyword phase.

static IEnumerable<int> GetPrimes(int from, int to)
{
for (int i = from; i <= to; i++)
{
if (!_worker.CancellationPending)
{
bool isPrime = true;
int limit = (int)Math.Sqrt(i);
for (int j = 2; j <= limit; j++)
if (i % j == 0)
{
isPrime = false;
break;
}
if (isPrime)
{
yield return i;
}
}
}
}

In the above 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, which helps us not to wait for whole result in one go. Try giving a bigger range like 1 to 10000 and you will be able to see the desired result.

Listed below are some of the basic rules which 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.