Enumerating a Collection
The .NET Framework provides enumerators as an easy way to iterate through a collection. Enumerators only read data in the collection; they cannot be used to modify the underlying collection.
Some languages provide a statement that calls the enumerator directly. The C# foreach statement and the Visual Basic for each statement use the enumerator to hide the complexity of manipulating the enumerator.
An enumerator flattens a collection so that the members can be accessed sequentially. Different collection classes might have different sequences. For example, an enumerator for an ArrayList preserves the order in which the elements are entered in the collection, whereas an enumerator for a Hashtable displays the elements according to the hash code of the element.
Every enumerator is based on the IEnumerator interface, which requires the following members:
- The Current property points to the current member in the collection.
- The MoveNext property moves the enumerator to the next member in the collection.
- The Reset property moves the enumerator back to the beginning of the collection. Current is positioned before the first element.
Behavior of an Enumerator
The enumerator is in an invalid state if it is positioned before the first element in the collection or after the last element in the collection. Whenever the enumerator is in an invalid state, calling Current throws an exception.
Initially, the enumerator is positioned before the first element in the collection. Reset also brings the enumerator back to this position. Therefore, after an enumerator is created or after a Reset, MoveNext must be called to advance the enumerator to the first element of the collection before reading the value of Current.
Current returns the same object until either MoveNext or Reset is called.
Once the end of the collection is passed, the enumerator is again in an invalid state, and calling MoveNext returns false. Calling Current throws an exception if the last call to MoveNext returned false.
The enumerator does not have exclusive access to the collection; therefore, other threads could still modify the collection.
An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the enumerator throws an InvalidOperationException the next time it is used.