TechQuiz Question 1 Why doesn't my code throw an exception?

2012-04-02

Inside VincisAqtion we’ve started with a little TechQuiz. We’re planning on  creating weekly questions to publish them on our intranet and next to the coffee machine.

The first question is: Why doesn’t the following code throw an exception?


static IEnumerable<char\> CapitalLetters(string input)  
{  
    if (input == null)  
    {  
        throw new ArgumentNullException(input);  
    }  
    foreach (char c in input)  
    {  
        yield return char.ToUpper(c);  
    }  
}

static void Main()  
{  
   CapitalLetters(null);  
}  

The code in this example won’t throw an Exception. This is because of the yield keyword within the foreach statement.

Yield is used to implement the ‘Iterator Pattern’. The idea behind this pattern is that you can iterate trough a collection without worrying about the underlying implementation (an array, list or a linked list or something else). Although we don’t realize it, we use this pattern daily.

Within .NET there are two interfaces that play a role in implementing the Iterator pattern: IEnumerator and IEnumerable. IEnumerable  defines a method: ‘GetEnumerator()’ that returns an instance of a class implementing  IEnumerator for that specific collection. An Enumerator acts likes a database cursor. It points to a specific row and it can only move forward.

The following demonstrates how you can use the IEnumerable and IEnumerator:


IEnumerable<char\> enumerable = CapitalLetters("Some text");  
IEnumerator<char\> enumerator = enumerable.GetEnumerator();

while (enumerator.MoveNext())
{
   char current = enumerator.Current;
   Console.WriteLine(current);
}

This code shows the complete iterator pattern. The method  CapitalLetters returns an  IEnumerable . The  IEnumerable returns an  IEnumerator . The  Enumerator can loop trough a collection while holding a reference to the current element.

The code inside  CapitalLetters  is executed when you call MoveNext(). So, the exception will only be thrown when you hit  MoveNext() for the first time.

But, I’ve never ever used this code! Why should I be interested?
Probably the following code will look familiar:


foreach (char current in CapitalLetters("Some text"))
{
   Console.WriteLine(current);
}

The C#  foreach statement is syntactic sugar for the iterator pattern. When the compiler finds a foreach keyword, it will automatically expand the code to use the  IEnumerator  and call  MoveNext() and  Current.

Why does this matter for your day to day job?

First off all, this sample makes it explicit how  foreach actually works. If you want to implement a custom collection you can use  IEnumerator and IEnumerable to implement the iterator pattern so it can be used in a foreach statement

Second off all, what if the method  CapitalLetters would have some really complex logic? When would this code be executed?

Each time you hit  MoveNext()!

So when using  foreach , it’s important to realize over what type of collection you are iterating. if your collection is calculated on the fly, this could mean a huge performance hit. Especially when you execute it multiple times. Adding a ToList() mean will iterate the collection for you and store the results.

This was our first TechQuiz question. If you have any comments or maybe ideas for a new question, please share :-)