tags:

views:

1436

answers:

2

Can someone share a simple example of using the foreach keyword with custom objects?

+15  A: 

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

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

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

where source implements IEnumerable<Foo> is roughly equivalent 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 the statement exits. This is important for iterator blocks.

To implement IEnumerable<T> or IEnumerator<T> yourself, the easiest way is to use an iterator block. Rather than write all the details here, it's probably best to just refer you to chapter 6 of C# in Depth, which is a free download. The whole of chapter 6 is on iterators. I have another couple of articles on my C# in 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 implement IEnumerable<T> for a type, you can do something like:

public class Foo implements 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
    }
}
Jon Skeet
The PDF direct link re-directs to the manning page - perhaps this will work better: http://www.manning.com/skeet/
Chris Kimpton
Thanks very much - fixing now. That's slightly annoying :(
Jon Skeet
A: 

(I assume C# here)

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

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

If you want to create your own container you can use the yield keyword (from .Net 2.0 and upwards I believe) together with 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 with foreach:

MyContainer myContainer = new MyContainer(10);
foreach(int i in myContainer)
    Console.WriteLine(i);
Mats Fredriksson