How do foreach loops work in C#?

user48616 picture user48616 · Dec 29, 2008 · Viewed 95.6k times · Source

Which types of classes can use foreach loops?

Answer

Marc Gravell picture Marc Gravell · Dec 30, 2008

Actually, strictly speaking, all you need to use foreach is a public GetEnumerator() method that returns something with a bool MoveNext() method and a ? Current {get;} property. However, the most common meaning of this is "something that implements IEnumerable/IEnumerable<T>, returning an IEnumerator/IEnumerator<T>.

By implication, this includes anything that implements ICollection/ICollection<T>, such as anything like Collection<T>, List<T>, arrays (T[]), etc. So any standard "collection of data" will generally support foreach.

For proof of the first point, the following works just fine:

using System;
class Foo {
    public int Current { get; private set; }
    private int step;
    public bool MoveNext() {
        if (step >= 5) return false;
        Current = step++;
        return true;
    }
}
class Bar {
    public Foo GetEnumerator() { return new Foo(); }
}
static class Program {
    static void Main() {
        Bar bar = new Bar();
        foreach (int item in bar) {
            Console.WriteLine(item);
        }
    }
}

How does it work?

A foreach loop like foreach(int i in obj) {...} kinda equates to:

var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
    int i; // C# 5.0
    i = tmp.Current;
    {...} // your code
}

However, there are variations. For example, if the enumerator (tmp) supports IDisposable, it is used too (similar to using).

Note the difference in the placement of the declaration "int i" inside (C# 5.0) vs. outside (up C# 4.0) the loop. It's important if you use i in an anonymous method/lambda inside your code-block. But that is another story ;-p