General explainations for enumeration
IEnumerable
is an interface, that is usually implemented by collection types in C#. For example List
, Queue
or Array
.
IEnumerable
provides a method GetEnumerator
which returns an object of type IEnumerator
.
The IEnumerator
basically represents a "forward moving pointer" to elements in a collection.
IEnumerator
has:
- the property
Current
, which returns the object it currently points to (e.g. first object in your collection).
- a method
MoveNext
, which moves the pointer to the next element. After calling it, Current
will hold a reference to the next object in your collection. MoveNext
will return false
if there were no more elements in the collection.
Whenever a foreach
loop is executed on an IEnumerable
, the IEnumerator
is retreived via GetEnumerator
and MoveNext
is called for each iteration - until it eventually returns false
. The variable you define in your loop header, is filled with the IEnumerator
's Current
.
Compiling a foreach loop
thx to @Llama
This code...
List<int> a = new List<int>();
foreach (var val in a)
{
var b = 1 + val;
}
is transformed to something like this by the compiler:
List<int> list = new List<int>();
List<int>.Enumerator enumerator = list.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
int current = enumerator.Current;
int num = 1 + current;
}
} finally {
((IDisposable)enumerator).Dispose();
}
The quote
The query represented by this method is not executed until the object
is enumerated either by calling its GetEnumerator method directly or
by using foreach in Visual C#.
GetEnumerator
is automatically called, as soon as you put your object into a foreach
loop, for example. Of course, other functions, e.g. Linq queries, can also retreive the IEnumerator
from your collection, by doing so either explicit (call GetEnumerator
) or implicit in some sort of loop, like I did in my sample above.