[ACCEPTED]-How to use foreach keyword on custom Objects in C#-foreach

Accepted answer
Score: 47

Given the tags, I assume you mean in .NET 15 - and I'll choose to talk about C#, as that's 14 what I know about.

The foreach statement (usually) uses 13 IEnumerable and IEnumerator or their generic cousins. A statement 12 of the form:

foreach (Foo element in source)
{
    // Body
}

where source implements IEnumerable<Foo> is roughly equivalent 11 to:

using (IEnumerator<Foo> iterator = source.GetEnumerator())
{
    Foo element;
    while (iterator.MoveNext())
    {
        element = iterator.Current;
        // Body
    }
}

Note that the IEnumerator<Foo> is disposed at the end, however 10 the statement exits. This is important for 9 iterator blocks.

To implement IEnumerable<T> or IEnumerator<T> yourself, the 8 easiest way is to use an iterator block. Rather 7 than write all the details here, it's probably 6 best to just refer you to chapter 6 of C# in Depth, which is a free 5 download. The whole of chapter 6 is on iterators. I 4 have another couple of articles on my C# in 3 Depth site, too:

As a quick example though:

public IEnumerable<int> EvenNumbers0To10()
{
    for (int i=0; i <= 10; i += 2)
    {
        yield return i;
    }
}

// Later
foreach (int x in EvenNumbers0To10())
{
    Console.WriteLine(x); // 0, 2, 4, 6, 8, 10
}

To 2 implement IEnumerable<T> for a type, you can do something 1 like:

public class Foo : IEnumerable<string>
{
    public IEnumerator<string> GetEnumerator()
    {
        yield return "x";
        yield return "y";
    }

    // Explicit interface implementation for nongeneric interface
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator(); // Just return the generic version
    }
}
Score: 10

(I assume C# here)

If you have a list of 7 custom objects you can just use the foreach 6 in the same way as you do with any other 5 object:

List<MyObject> myObjects = // something
foreach(MyObject myObject in myObjects)
{
     // Do something nifty here
}

If you want to create your own container 4 you can use the yield keyword (from .Net 3 2.0 and upwards I believe) together with 2 the IEnumerable interface.

class MyContainer : IEnumerable<int>
{
    private int max = 0;
    public MyContainer(int max)
    {
        this.max = max;
    }

    public IEnumerator<int> GetEnumerator()
    {
        for(int i = 0; i < max; ++i)
            yield return i;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

And then use it 1 with foreach:

MyContainer myContainer = new MyContainer(10);
foreach(int i in myContainer)
    Console.WriteLine(i);
Score: 1

From MSDN Reference:

The foreach statement is not limited 11 to IEnumerable types and can be applied to an instance 10 of any type that satisfies the following 9 conditions:

has the public parameterless 8 GetEnumerator method whose return type is either class, struct, or 7 interface type, the return type of the GetEnumerator method 6 has the public Current property and the 5 public parameterless MoveNext method whose return 4 type is Boolean.

If you declare those methods, you 3 can use foreach keyword without IEnumerable overhead. To verify 2 this, take this code snipped and see that 1 it produces no compile-time error:

class Item
{
    public Item Current { get; set; }
    public bool MoveNext()
    {
        return false;
    }
}

class Foreachable
{
    Item[] items;
    int index;
    public Item GetEnumerator()
    {
        return items[index];
    }
}

Foreachable foreachable = new Foreachable();
foreach (Item item in foreachable)
{

}

More Related questions