tags:

views:

3049

answers:

6

I don't understand which types of classes can use foreach loops. Please help!

A: 

Just call foreach loops on any classes that implement the IEnumerable and IEnumerator classes...

ie:

public MYClass : IEnumerator, IEnumerable { 
    /*implement the interfaces */ 
}
mirezus
That is not correct, the bottommost answer is though.
leppie
technically its not incorrect, it just doesn't say that it also works on any class with the GetEnumerator (etc).
Jeff Martin
IEnumerator is also irrelevant - if the "and" is meant to mean "it has to implement both" then it's incorrect; if it's meant to mean "or it could just implement IEnumerator" then it's also incorrect.
Jon Skeet
+2  A: 

From MSDN:

The foreach statement repeats a group of embedded statements for each element in an array or an object collection. The foreach statement is used to iterate through the collection to get the desired information, but should not be used to change the contents of the collection to avoid unpredictable side effects. (emphasis mine)

So, if you have an array, you could use the foreach statement to iterate through the array, like so:

 int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
    foreach (int i in fibarray)
    {
        System.Console.WriteLine(i);
    }

You could also use it to iterate through a List<T> collection, like so:

List<string> list = new List<string>();

foreach (string item in list)
{
    Console.WriteLine(item);
}
George Stocker
oddly enough, according to MSDN (http://msdn.microsoft.com/en-us/library/9yb8xew9(VS.80).aspx), objects types don't need to implement IEnumerable. Any type that defines GetEnumerator, MoveNext, Reset and Current the correct way will work. Weird, huh?
Sean Reilly
Neat. I didn't know that. :-)
George Stocker
+47  A: 

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;
while(tmp.MoveNext()) {
    i = tmp.Current;
    {...} // your code
}

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

Note that the positioning of "int i" outside the loop is important if you use i in an anonymous method/lambda inside your code-block. But that is another story ;-p

Marc Gravell
+1 for going in depth. I normally don't go that in depth for a question that may be a 'beginner' question since it would seem overwhelming to the new programmer.
George Stocker
True, Gortok - so I followed up with the stuff about lists/arrays/etc.
Marc Gravell
+1 Great answer, didnt know about this
Andreas Grech
Would be good to mention the implicit runtime casting to the loop variable - can produce type incompatibility exceptions.
Daniel Earwicker
Shouldn't the first line inside the `while` loop be `i = tmp.Current;`?
Jason
@Jason - good spot; braindead moment by me
Marc Gravell
+1  A: 

According to this post (http://blogs.msdn.com/kcwalina/archive/2007/07/18/DuckNotation.aspx) duck typing is used.

tuinstoel
+1  A: 

Here's the docs: Main article With Arrays With Collection Objects

It's important to note that "The type of the collection element must be convertible to the identifier type". This sometimes cannot be checked at compile time and can generate a runtime exception if the instance type is not assignable to the reference type.

This will generate a runtime exception if there is an non-Apple in the fruit basket, such as an orange.

List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)

This safely filters the list to only the Apples using Enumerable.OfType

foreach(Apple a in fruitBasket.OfType<Apple>() )
David B
+1  A: 

I think the best answer given by "Marc Gravell" but I want to add some notes: do not change your IEnumerable object inside the foreach do not change your Iterator object inside the foreach avoid foreach on the collections that are being used by different threads except you are handling this matter

Ahmed Said