Desugaring foreach

When working with data you often work with collections. This could be an array, one of the .NET Framework collections or maybe even a custom collection type.

Iterating over the elements in a collection is such a common task that the creators of C# added some syntactic sugar to make this task even easier in the form of the foreach statement. Understanding what’s going on behind the scenes can help you when working with collections and it can show you new ways to improve your own collection types.

What if there was no syntactic sugar?

Let’s say you have an array containing some integers and you where asked to display them on screen without using the foreach statement. What would you use?

Well, you could use a for loop like this:

   1:  using System;
   2:   
   3:  namespace Foreach
   4:  {
   5:      class Program
   6:      {
   7:          static void Main(string[] args)
   8:          {
   9:              int[] numbers = { 1, 1, 2, 3, 5, 8, 13 };
  10:   
  11:              for (int index = 0; index < numbers.Length; index++)
  12:              {
  13:                  int current = numbers[index];
  14:                  Console.WriteLine(current);
  15:              }
  16:   
  17:              Console.ReadLine();
  18:          }
  19:      }
  20:  }

By keeping track of where you are in the collection and finding the current element you can iterate quite easily over all the elements in the array.

Another way would be to use a while loop:

   1:  using System;
   2:   
   3:  namespace Foreach
   4:  {
   5:      class Program
   6:      {
   7:          static void Main(string[] args)
   8:          {
   9:              int[] numbers = { 1, 1, 2, 3, 5, 8, 13 };
  10:              
  11:              int index = 0;
  12:              while (index < numbers.Length)
  13:              {
  14:                  int current = numbers[index];
  15:                  Console.WriteLine(current);
  16:                  index++;
  17:              }
  18:   
  19:              Console.ReadLine();
  20:          }
  21:      }
  22:  }

Under the covers, a for statement is usually implemented using a while loop. If you compare both statements, you see a couple of similarities. Both use an index to keep track of where they are in the collection and check the length of the collection. They also fetch the current item for you so you can use it. Because of these similarities, it would be nice to have a language construct that made it easier to use collections. Fortunately, that’s exactly what the foreach statement does.

Using some syntactic sugar: foreach

The foreach statement is syntactic sugar that allows you to easily work with collections. The previous examples can be rewritten to use foreach:

   1:  using System;
   2:   
   3:  namespace Foreach
   4:  {
   5:      class Program
   6:      {
   7:          static void Main(string[] args)
   8:          {
   9:              int[] numbers = { 1, 1, 2, 3, 5, 8, 13 };
  10:   
  11:              foreach (int current in numbers)
  12:              {
  13:                  Console.WriteLine(current);
  14:              }     
  15:   
  16:              Console.ReadLine();
  17:          }
  18:      }
  19:  }

When you are working on an array, the compiler is smart enough to translate your code to a basic for loop. This gives you the best performance when working with arrays.

When you are working with a more complex collection, like a List<int> you get a different behavior. When working with such a collection, the IEnumerable and IEnumerator interfaces are used to implement the iterator pattern.

In essence, foreach translates into the following C# code:

   1:  List<int>.Enumerator e = numbers.GetEnumerator();
   2:   
   3:  try
   4:  {
   5:      int v;
   6:      while (e.MoveNext())
   7:      {
   8:          v = e.Current;
   9:          Console.WriteLine(v);
  10:      }
  11:  }
  12:  finally
  13:  {
  14:      IDisposable d = e as IDisposable;
  15:      if (d != null) d.Dispose();
  16:  }

Your collection exposes a method called GetEnumerator. The enumerator object keeps track of where it is in the collection and offers you access to the current item. By using the while loop, you can move trough all elements in the collection. The try/finally block is added to make sure that you always dispose of the enumerator if it implements IDisposable.

And that’s how the foreach statement works. As you can understand, there is a whole lot more to creating your own enumerator objects and making sure that your collection can be used in a foreach statement. This concerns things like implementing a GetEnumerator method, the IEnumerable interface, using dynamic and using some other syntactic sugar: yield.

But that’s a topic for next time!

Questions? Feedback? Please leave a comment!

Share

Leave a Reply

Your email address will not be published. Required fields are marked *

Post comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.