86

Which types of classes can use foreach loops?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user48616
  • 901
  • 1
  • 7
  • 4
  • 5
    You may want to choose a different accepted answer, since the one you selected isn't really representative of the correct answer. – George Stocker Dec 30 '08 at 02:02

7 Answers7

167

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

mshwf
  • 7,009
  • 12
  • 59
  • 133
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 3
    +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 Dec 29 '08 at 23:05
  • True, Gortok - so I followed up with the stuff about lists/arrays/etc. – Marc Gravell Dec 29 '08 at 23:06
  • Would be good to mention the implicit runtime casting to the loop variable - can produce type incompatibility exceptions. – Daniel Earwicker Jul 11 '09 at 06:58
  • Shouldn't the first line inside the `while` loop be `i = tmp.Current;`? – jason Jan 27 '10 at 02:55
  • 3
    Don't forget: When using a array with foreach the compiler creates a simple `for-loop`( You can see this when working with IL ). – Felix K. May 14 '12 at 13:00
  • @Marc Gravell: Yes, the location of "i" is important to what happens with lambdas, but you got it wrong. "i" is placed **inside** the loop. The language spec says `The placement of v inside the while loop is important for how it is captured by any anonymous function occurring in the embedded-statement.` (with "v" being your "i"). It even gives an example. – Paul Groke Aug 23 '13 at 03:40
  • @PaulGroke no, I didn't "get it wrong". The specification **changed** in C# 5 - i.e. pretty recently. This answer was Dec '08. Prior to C# 5, the placement was semantically **outside** the `while` - see http://stackoverflow.com/a/12112959 – Marc Gravell Aug 23 '13 at 06:46
  • @Marc Gravell: Oh, I'm sorry, I didn't know that! I just checked the current spec, and assumed ... Well, thanks for the clarification! :-) – Paul Groke Aug 23 '13 at 16:53
  • @Paul well, thanks for prompting me to tweak the answer slightly to account for the change – Marc Gravell Aug 23 '13 at 17:02
  • 1
    @Marc Gravell: OK, cool! I edited the post to make it more clear - at least to me. After all the placement isn't only important in C# 5.0, it's always important, only that it changed. I hope you don't mind. – Paul Groke Aug 23 '13 at 17:30
  • Here is a good auricle with examples of how things work: https://learn.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8 – maxc137 Apr 19 '20 at 12:33
7

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
  • 57,289
  • 29
  • 176
  • 237
  • 4
    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 Dec 29 '08 at 23:01
  • Neat. I didn't know that. :-) – George Stocker Dec 29 '08 at 23:02
4

According to the blog post Duck Notation, duck typing is used.

Pang
  • 9,564
  • 146
  • 81
  • 122
tuinstoel
  • 7,248
  • 27
  • 27
2

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>() )
Amy B
  • 108,202
  • 21
  • 135
  • 185
-1
IList<ListItem> illi = new List<ListItem>();
ListItem li = null;

foreach (HroCategory value in listddlsubcategory)
{
    listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id);
    li = new ListItem();
    li.Text = value.Description;
    li.Value = value.Id.ToString();
    illi.Add(li);
    IList<ListItem> newilli = new List<ListItem>();
    newilli = SubCatagoryFunction(listddlsubcategoryext, "-->");
    foreach (ListItem c in newilli)
    {
        illi.Add(c);
    }
}
kayess
  • 3,384
  • 9
  • 28
  • 45
-1

Useful info regarding this subject can be found on MSDN too. Taking the essence from that article:

The foreach keyword enumerates a collection, executing the embedded statement once for each element in the collection:

foreach (var item in collection)
{
    Console.WriteLine(item.ToString());
}

The compiler translates the foreach loop shown in the above example into something similar to this construct:

IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
    var item = enumerator.Current;
    Console.WriteLine(item.ToString());
}
r23
  • 293
  • 6
  • 12
-2

you can try this...

List<int> numbers = new List<int>();
        numbers.Add(5);
        numbers.Add(15);
        numbers.Add(25);
        numbers.Add(35);

        Console.WriteLine("You are added total number: {0}",numbers.Count);
        foreach (int number in numbers)
        {
            Console.WriteLine("Your adding Number are: {0}", number);
        }
Dedarul
  • 1
  • 1