Often you will want to cycle through the elements in a collection. For example, you might want to display each element. One way to do this is to use a foreach loop, as the preceding examples have done. Another way is to use an enumerator. An enumerator is an object that implements either the non-generic IEnumerator or the generic IEnumerator interface.
Recall that IEnumerator defines one property called Current. The non-generic version is shown here:
object Current { get; }
For IEnumerator , Current is declared like this:
T Current { get; }
In both cases, Current obtains the current element being enumerated. Since Current is a read-only property, an enumerator can only be used to retrieve, but not modify, the objects in a collection.
Also recall that IEnumerator defines two methods. The first is MoveNext( ):
bool MoveNext( )
Each call to MoveNext( ) moves the current position of the enumerator to the next element in the collection. It returns true if the next element is available, or false, if the end of the collection has been reached. Prior to the first call to MoveNext( ), the value of Current is undefined. (Conceptually, prior to the first call to MoveNext( ), the enumerator refers to the non-existent element that is just before the first element. Thus, you must call MoveNext( ) to move to the first element.)
You can reset the enumerator to the start of the collection by calling Reset( ), shown here:
void Reset( )
After calling Reset( ), enumeration will again begin at the start of the collection. Thus, you must call MoveNext( ) before obtaining the first element.
IEnumerator inherits the methods MoveNext( ) and Reset( ) from IEnumerator and they work in the same way.
Using an Enumerator
Before you can access a collection through an enumerator, you must obtain one. Each of the collection classes provides a GetEnumerator( ) method that returns an enumerator to the start of the collection. Using this enumerator, you can access each element in the collection, one element at a time. In general, to use an enumerator to cycle through the contents of a collection, follow these steps:
-
Obtain an enumerator to the start of the collection by calling the collection’s GetEnumerator( ) method. -
Set up a loop that makes a call to MoveNext( ). Have the loop iterate as long as MoveNext( ) returns true. -
Within the loop, obtain each element through Current.
Here is an example that implements these steps. It uses an ArrayList, but the general principles apply to any type of collection, including the generic collections.
// Demonstrate an enumerator. using System; using System.Collections; class EnumeratorDemo { public static void Main() { ArrayList list = new ArrayList(1); for(int i=0; i < 10; i++) list.Add(i); // Use enumerator to access list. IEnumerator etr = list.GetEnumerator(); while(etr.MoveNext()) Console.Write(etr.Current + " "); Console.WriteLine(); // Re-enumerate the list. etr.Reset(); while(etr.MoveNext()) Console.Write(etr.Current + " "); Console.WriteLine(); } }
The output is shown here:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
In general, when you need to cycle through a collection, a foreach loop is more convenient to use than an enumerator. However, an enumerator gives you a little extra control by allowing you to reset the enumerator at will.
Using the IDictionaryEnumerator
When using a non-generic IDictionary, such as Hashtable, you will use an IDictionaryEnumerator instead of an IEnumerator when cycling through the collection. The IDictionaryEnumerator inherits IEnumerator and adds three properties. The first is
DictionaryEntry Entry { get; }
Entry obtains the next key/value pair from the enumerator in the form of a DictionaryEntry structure. Recall that DictionaryEntry defines two properties, called Key and Value, which can be used to access the key or value contained within the entry. The other two properties defined by IDictionaryEnumerator are shown here:
object Key { get; } object Value { get; }
These allow you to access the key or value directly.
An IDictionaryEnumerator is used just like a regular enumerator, except that you will obtain the current value through the Entry, Key, or Value properties rather than Current. Thus, after obtaining an IDictionaryEnumerator, you must call MoveNext( ) to obtain the first element. Continue to call MoveNext( ) to obtain the rest of the elements in the collection. MoveNext( ) returns false when there are no more elements.
Here is an example that enumerates the elements in a Hashtable through an IDictionaryEnumerator:
// Demonstrate IDictionaryEnumerator. using System; using System.Collections; class IDicEnumDemo { public static void Main() { // Create a hash table. Hashtable ht = new Hashtable(); // Add elements to the table ht.Add("Tom", "555−3456"); ht.Add("Mary", "555−9876"); ht.Add("Todd", "555−3452"); ht.Add("Ken", "555−7756"); // Demonstrate enumerator IDictionaryEnumerator etr = ht.GetEnumerator(); Console.WriteLine("Display info using Entry."); while(etr.MoveNext()) Console.WriteLine(etr.Entry.Key + ": " + etr.Entry.Value); Console.WriteLine(); Console.WriteLine("Display info using Key and Value directly."); etr.Reset(); while(etr.MoveNext()) Console.WriteLine(etr.Key + ": " + etr.Value); } }
The output is shown here:
Display info using Entry. Ken: 555−7756 Mary: 555−9876 Tom: 555−3456 Todd: 555−3452 Display info using Key and Value directly. Ken: 555−7756 Mary: 555−9876 Tom: 555−3456 Todd: 555−3452
No comments:
Post a Comment