Monthly Archives: August 2010

Pop Quiz! How do you make your type enumerable using the foreach keyword?

This week I started my Masters in Software Engineering program at Carnegie Mellon Silicon Valley. So far it’s been a great experience; the school had an orientation that was fun and informative, I’ve met the teammates I’ll be working with in my first course (every course in this program revolves around working on a team), and already I have found myself diving headfirst into a new methodology and a new programming language: XP (Extreme Programming) and Ruby on Rails.

So it seems highly likely that this blog will start to focus on some very non-.NET things in the coming months. That said, I am still working at my current job for a trading firm in Philadelphia, where we’re using .NET; so I am sure to continue writing posts on that topic as well.

And eventually, maybe I’ll even get around to fulfilling the “philosopher” part of my blog title and actually post some of my thoughts and ideas that have nothing to do with programming. But these days, such thoughts and ideas are fairly rare.

Anyway, for this post I wanted to point out something a little bit cool/weird about C# that most developers are (I’m fairly certain) unaware of. It’s actually the falsehood of something most C# developers believe that is surprising. Here is the widespread belief that happens to be false:

In order for external code to enumerate over my type using foreach, I need to implement IEnumerable (and preferably IEnumerable<T>).

Well, that certainly appears to be the case, right? Otherwise, how could foreach possibly work?

The answer is that foreach actually requires a pattern, not an interface.

That pattern is as follows:

1. The type of object being enumerated over must supply a GetEnumerator method.
2. The type of object returned by said GetEnumerator method must supply a Current property and a MoveNext method.

In other words, this is basically duck typing in .NET. If it walks like an IEnumerable<T> and talks like an IEnumerable<T>, well then, we’ll treat it as one!

For a simple demonstration of this feature, take a look at the following code:

class NaturalNumbers
{
	public class NaturalNumberEnumerator
	{
		private int m_max;
		private int m_value;
		
		public NaturalNumberEnumerator(int max)
		{
			m_max = max;
		}
		
		public int Current
		{
			get
			{
				if (m_value < 1)
				{
					throw new InvalidOperationException();
				}
				
				return m_value;
			}
		}
		
		public bool MoveNext()
		{
			if (m_value == -1)
			{
				return false;
			}
			else if (m_value >= m_max)
			{
				m_value = -1;
				return false;
			}
			
			++m_value;
			return true;
		}
	}
	
	private int m_max;
	
	private NaturalNumbers(int max)
	{
		m_max = max;
	}
	
	public static NaturalNumbers UpTo(int number)
	{
		return new NaturalNumbers(number);
	}
	
	public NaturalNumberEnumerator GetEnumerator()
	{
		return new NaturalNumberEnumerator(m_max);
	}
}

With the above code in place, I can do this:

foreach (int number in NaturalNumbers.UpTo(50))
{
    Console.WriteLine(number);
}

Notice the NaturalNumbers class does not implement IEnumerable<int>, nor does the NaturalNumberEnumerator class implement IEnumerator<int> — they just act like they do.

So, foreach without any interfaces! Well I’ll be darned…

Advertisements