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 :-)