A closer look at yield


The yield keyword in C# is pretty powerful and expressive, but it doesn’t seem to be very widely known about. In this post we’ll take a quick look at what yield does and then I’ll post a follow-up that looks at what the compiler generates for you. Let’s start by looking at a simple (and contrived) example:


private static readonly string[] StringValues = new string[] { “The”, “quick”, “brown”, “fox”, 
                            “jumped”, “over”, “the”, “lazy”, “dog” };
static IEnumerable<string> TestIterator()
{
foreach(string value in StringValues)
{
yield return value;
}
}

The return type for the TestIterator method is IEnumerable<string>, but you can see that we don’t have a return statement in the implementation. Instead, we’re using the yield return statement to return each item that we want the caller to operate on. The compiler automatically generates a class that implements IEnumerable<string> for us. We can call this function using the following code:


foreach(string value in TestIterator())
{
Console.WriteLine(“In foreach:{0}”, value);
}

This code will iterate over the IEnumerable<string> instance that is returned from the TestIterator method. In this example we’ve simply iterated over an existing collection, so we’re not providing much functionality! A more interesting example would be for a binary tree such as:


class BinaryTree<T>
{
public T Item { get; set; }
public BinaryTree<T> Left { get; set; }
public BinaryTree<T> Right { get; set; }
}

In this case, the yield keyword makes it a breeze to add IEnumerable support. First, we add IEnumerable<T> to the implemented interfaces and then we just need the code below to provide the implementation:


public IEnumerator<T> GetEnumerator()
{
yield return Item;
if (Left != null)
{
foreach (T t in Left)
{
yield return t;
}
}
if (Right != null)
{
foreach (T t in Right)
{
yield return t;
}
}
}

This code returns the item for the current node and then recurses into the items from the left and right hand of the tree – how easy is that? This is one of the big advantages of the yield keyword: it allows you to write readable and concise code to produce an iterator.


Stay tuned for part 2, when we’ll take a look at the code that the compiler generates for us…

Comments (3)

  1. Stuart Leeks says:

    In part 1 , we took a quick tour of the yield keyword. In this post we’re going to have a look at the

  2. This is an interesting feature that I saw in one of the feeds that is on my list. Follow the text and