Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Daniel Solis - Illustrated C# 2010 - 2010.pdf
Скачиваний:
16
Добавлен:
11.06.2015
Размер:
11.23 Mб
Скачать

CHAPTER 20 ENUMERATORS AND ITERATORS

Using the IEnumerator Interface

This section will start by looking at the first in the preceding list: the nongeneric interface form. This form of enumerator is a class that implements the IEnumerator interface. It's called nongeneric because it does not use C# generics.

The IEnumerator interface contains three function members: Current, MoveNext, and Reset.

Current is a property that returns the item at the current position in the sequence.

It is a read-only property.

It returns a reference of type object, so an object of any type can be returned.

MoveNext is a method that advances the enumerator’s position to the next item in the collection. It also returns a Boolean value, indicating whether the new position is a valid position or is beyond the end of the sequence.

If the new position is valid, the method returns true.

If the new position isn't valid (that is, it’s beyond the end), the method returns false.

The initial position of the enumerator is before the first item in the sequence. MoveNext must be called before the first access of Current.

Reset is a method that resets the position to the initial state.

Figure 20-2 illustrates a collection of three items, which is shown on the left of the figure, and its enumerator, which is shown on the right. In the figure, the enumerator is an instance of a class called

ArrEnumerator.

Figure 20-2. The enumerator for a small collection

508

CHAPTER 20 ENUMERATORS AND ITERATORS

The enumerator class is usually declared as a nested class of the class for which it is an enumerator. A nested class is declared inside the declaration of another class. Nested classes are described in detail in Chapter 25.

The way the enumerator keeps track of the current item in the sequence is entirely implementationdependent. It might be implemented as a reference to an object, an index value, or something else entirely. In the case of the built-in single-dimensional array type, it’s simply the index of the item.

Figure 20-3 illustrates the states of an enumerator for a collection of three items. The states are labeled 1 through 5.

Notice that in state 1, the initial position of the enumerator is -1 (that is, before the first element of the collection).

Each transition between states is caused by a call to MoveNext, which advances the position in the sequence. Each call to MoveNext between states 1 and 4 returns true. In the transition between states 4 and 5, however, the position ends up beyond the last item in the collection, so the method returns false.

In the final state, any further calls to MoveNext return false.

Figure 20-3. The states of an enumerator

509

CHAPTER 20 ENUMERATORS AND ITERATORS

Given a collection’s enumerator, you should be able to simulate a foreach loop by cycling through the items in the collection using the MoveNext and Current members. For example, you know that arrays are enumerable, so the following code does manually what the foreach statement does automatically. In fact, the C# compiler generates exactly this code when you write a foreach loop.

static void Main()

 

{

 

int[] MyArray = { 10, 11, 12, 13 };

// Create an array.

 

 

IEnumerator ie = MyArray.GetEnumerator();

// Get its enumerator.

while ( ie.MoveNext() )

// Move to the next item.

{

 

int i = (int) ie.Current; Console.WriteLine("{0}", i);

}

}

//Get the current item.

//Write it out.

This code produces the following output:

10

11

12

13

510

CHAPTER 20 ENUMERATORS AND ITERATORS

Declaring an IEnumerator Enumerator

To create a nongeneric interface enumerator class, you must declare a class that implements the IEnumerator interface. The IEnumerator interface has the following characteristics:

It is a member of the System.Collections namespace.

It contains the three members Current, MoveNext, and Reset.

The following code shows the outline of a nongeneric enumerator class. It does not show how the position is maintained. Notice that Current returns a reference to an object.

using System.Collections;

 

// Include the namespace.

class MyEnumerator: IEnumerator

 

{

Returns a reference to an object

 

 

 

 

public

object Current

{ get; }

// Current

 

 

 

public

bool MoveNext() { ... }

// MoveNext

public

void Reset()

{ ... }

// Reset

...

 

 

 

}

 

 

 

511

CHAPTER 20 ENUMERATORS AND ITERATORS

For example, the following code implements an enumerator class that lists an array of color names:

using System.Collections;

 

 

class ColorEnumerator: IEnumerator

 

{

 

string[] Colors;

Implements IEnumerator

 

int Position = -1;

 

 

public object Current

 

// Current

{

 

 

get

 

 

{

 

 

if (Position == -1)

 

throw new InvalidOperationException();

 

if (Position == Colors.Length)

 

throw new InvalidOperationException();

 

return Colors[Position];

 

}

 

 

}

 

 

public bool MoveNext()

 

// MoveNext

{

 

 

if (Position < Colors.Length - 1)

 

{

 

 

Position++;

 

 

return true;

 

 

}

 

 

else

 

 

return false;

 

 

}

 

 

public void Reset()

 

// Reset

{

 

 

Position = -1;

 

 

}

 

 

public ColorEnumerator(string[] theColors)

// Constructor

{

 

 

Colors = new string[theColors.Length];

for (int i = 0; i < theColors.Length; i++) Colors[i] = theColors[i];

}

}

512

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]