As mentioned earlier, normally it is easier (and better) to use a foreach loop to cycle through a collection than it is to explicitly use IEnumerator methods. However, understanding the operation of these interfaces is important for another reason: If you want to create a class that contains objects that can be enumerated via a foreach loop, then that class must implement IEnumerator. It must also implement IEnumerable. In other words, to enable an object of a class that you create to be used in a foreach loop, you must implement IEnumerator and IEnumerable, using either their generic or non-generic form. Fortunately, because these interfaces are so small, they are easy to implement.
Here is an example that implements the non-generic versions of IEnumerable and IEnumerator so that the contents of the array encapsulated within MyClass can be enumerated.
// Implement IEnumerable and IEnumerator. using System; using System.Collections; class MyClass : IEnumerator, IEnumerable { char[] chrs = { 'A', 'B', 'C', 'D' }; int idx = -1; // Implement IEnumerable. public IEnumerator GetEnumerator() { return this; } // The following methods implement IEnumerator. // Return the current object. public object Current { get { return chrs[idx]; } } // Advance to the next object. public bool MoveNext() { if(idx == chrs.Length-1) { Reset(); // reset enumerator at the end. return false; } idx++; return true; } // Reset the enumerator to the start. public void Reset() { idx = -1; } } class EnumeratorImplDemo { public static void Main() { MyClass mc = new MyClass(); // Display the contents of mc. foreach(char ch in mc) Console.Write(ch + " "); Console.WriteLine(); // Display the contents of mc, again. foreach(char ch in mc) Console.Write(ch + " "); Console.WriteLine(); } }
Here is the output:
A B C D A B C D
In the program, first examine MyClass. It encapsulates a small char array that contains the characters A through D. An index into this array is stored in idx, which is initialized to −1. MyClass then implements both IEnumerator and IEnumerable. GetEnumerator( ) returns a reference to the enumerator, which in this case is the current object. The Current property returns the next character in the array, which is the object at idx. The MoveNext( ) method advances idx to the next location. It returns false if the end of the collection has been reached and true otherwise. Reset( ) sets idx to −1. Recall that an enumerator is undefined until after the first call to MoveNext( ). Thus, in a foreach loop, MoveNext( ) is automatically called before Current. This is why idx must initially be −1; it is advanced to zero when the foreach loop begins. A generic implementation would work in a similar fashion.
Inside Main( ), an object of type MyClass called mc is created, and the contents of the object are twice displayed by use of a foreach loop.
No comments:
Post a Comment