I am currently looking for a contract in the London area -

If you're hiring a .NET contractor in or around London, look no further!

Iterator blocks and the "yield return" statement - #1


This is the first part of a two-part series. For the second post, see Iterator blocks and the "yield return" statement - #2.

C# 2.0 introduced a wonderful and underused piece of syntax - the "yield return" statement. This is the first of two posts - in this one I will explain what yield return is and how to use it, and in the second of I'll explain how it actually works internally.

Iterators

An iterator in C# is a coding construct that allows you to loop over a set of values using the foreach loop, without having to implement the entire IEnumerator interface. If you've ever rolled your own collection classes that needed you to implement IEnumerator, you might know what pain it can sometimes be. In particular, it is difficult to implement on non-linear data structures, such as trees, without some nasty hacking.

C# 2.0 allows us to avoid implementing the full IEnumerator interface, by writing a special iterator method, using yield return to provide values back to the caller. Such a method is called an iterator block - a method that returns either IEnumerable or IEnumerable<> - which can be either an instance or a static method.

Yield return

The yield return statement is used to return a single value from the iterator block. A simple example is below (taken from the MSDN documentation)
public static IEnumerable Power(int number, int exponent)
{
    int counter = 0;
    int result = 1;
    while (counter++ < exponent)
    {
        result = result * number;
        yield return result;
    }
}
In this example, the yield return statement is executed once per loop, returning the next value in the power set for the given parameters. It doesn't need to be used in a loop however - the following is perfectly valid:
public static IEnumerable Workdays()
{
 yield return "Monday";
 yield return "Tuesday";
 yield return "Wednesday";
 yield return "Thursday";
 yield return "Friday";
}

static void Main()
{
 foreach (string day in Workdays())
 {
  Console.WriteLine(day);
 }
}


Limitations

You can't nest yield return statements inside a try.. catch block, it can't be unsafe code, and can't appear in an anonymous method or lambda expression. Also, the iterator block cannot take ref or out parameters. This is all due to the way yield return is implemented internally, which I will be covering in the next post of this series.

0 comments: