foreach
enumerates any object that implements IEnumerable
, IEnumerable<T>
, IEnumerator
, or IEnumerator<T>
(or actually any object whose class implements a compatible Current
property and MoveNext()
method). The syntax for foreach
is:
foreach (type variable in enumerable) { ... }
type
is the type of the new variable
variable. (If you already have an existing variable to use then omit the type.)
The body of the loop will be executed for each object in the enumerable, and the iteration variable (here variable
) will contain the object on each iteration.
for
is much more general-purpose, and follows this pattern:
for (initial-statements; loop-condition; post-iteration-actions) {
body
}
Which is almost exactly equivalent to:
initial-statements
while (loop-condition) {
body
post-iteration-actions
}
You may see a for
loop when dealing with arrays, for example:
for (int index = 0; index < array.Length; index++) {
Console.WriteLine(array[index]);
}
This is the same thing as:
{
int index = 0;
while (index < array.Length) {
Console.WriteLine(array[index]);
index++;
}
}
(Note that using foreach
over arrays is optimized by the compiler to use a similar index-based iteration, since this is faster. So all three approaches should have equivalent performance and runtime semantics when enumerating an array.)
Further information, if you want it:
foreach
is actually just syntactic sugar, and can be easily translated into a while
loop.
foreach (object x in y) {
Console.WriteLine(x);
}
This actually means:
var enumerator = y.GetEnumerator();
try {
object x; // See footnote 1
while (enumerator.MoveNext()) {
x = enumerator.Current;
Console.WriteLine(x);
}
} finally {
((IDisposable)enumerator).Dispose();
}
Except that the enumerator
variable has no name and is hidden from you.
It's pretty obvious why foreach
exists. Everywhere you use it today you would otherwise have to write this horribly verbose boilerplate code. foreach
takes care of everything for you -- grabbing an enumerator, testing MoveNext()
on each iteration, extracting the enumerator's current value, and disposing of the enumerator after iteration completes.
1 This variable is actually semantically declared inside of the loop, starting with C# 5. This example is accurate for C# 4 and predecessors.