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

CHAPTER 20 ENUMERATORS AND ITERATORS

Producing Multiple Enumerators

The previous example used iterators to produce a class with two enumerables. This example shows two things. First, it uses iterators to produce a class with two enumerators. Second, it shows how iterators can be implemented as properties rather than methods.

The code declares two properties that define two different enumerators. The GetEnumerator method returns one or the other of the two enumerators, depending on the value of the Boolean variable ColorFlag. If ColorFlag is true, the Colors enumerator is returned. Otherwise, the BlackAndWhite enumerator is returned.

class MyClass: IEnumerable<string>

{

bool ColorFlag = true;

 

public MyClass(bool flag)

// Constructor

{

 

ColorFlag = flag;

 

}

 

IEnumerator<string> BlackAndWhite

// Property--enumerator iterator

{

 

get

 

{

 

yield return "black";

 

yield return "gray";

 

yield return "white";

 

}

 

}

 

IEnumerator<string> Colors

// Property--enumerator iterator

{

 

get

 

{

 

string[] theColors = { "blue", "red", "yellow" }; for (int i = 0; i < theColors.Length; i++)

yield return theColors[i];

}

}

534

CHAPTER 20 ENUMERATORS AND ITERATORS

public IEnumerator<string> GetEnumerator() // GetEnumerator

{

 

 

 

return ColorFlag

 

 

 

? Colors

//

Return

Colors enumerator

: BlackAndWhite;

//

Return

BlackAndWhite enumerator

}

 

 

 

System.Collections.IEnumerator

System.Collections.IEnumerable.GetEnumerator()

{

return ColorFlag

 

 

? Colors

 

// Return Colors enumerator

: BlackAndWhite;

// Return BlackAndWhite enumerator

}

 

 

}

 

 

class Program

 

 

{

 

 

static void Main()

 

 

{

 

 

MyClass mc1 = new MyClass( true );

// Call constructor with true

foreach (string s in mc1)

 

Console.Write("{0}

", s);

 

Console.WriteLine();

 

 

MyClass mc2 = new MyClass( false );

// Call constructor with false

foreach (string s in mc2)

 

Console.Write("{0}

", s);

 

Console.WriteLine();

 

 

}

 

 

}

 

 

This code produces the following output:

blue red yellow black gray white

535

CHAPTER 20 ENUMERATORS AND ITERATORS

Behind the Scenes with Iterators

The following are some other important things to know about iterators:

Iterators require the System.Collections.Generic namespace, so you should include it with a using directive.

In the compiler-generated enumerators, the Reset method is not supported. It is implemented, since it is required by the interface, but the implementation throws a

System.NotSupportedException exception if it is called. Notice that the Reset method is shown grayed out in Figure 20-9.

Behind the scenes, the enumerator class generated by the compiler is a state machine with four states:

Before: The initial state before the first call to MoveNext.

Running: The state entered when MoveNext is called. While in this state, the enumerator determines and sets the position for the next item. It exits the state when it encounters a yield return, a yield break, or the end of the iterator body.

Suspended: The state where the state machine is waiting for the next call to MoveNext. After: The state where there are no more items to enumerate.

If the state machine is in either the before or suspended states and there is a call to the MoveNext method, it goes into the running state. In the running state, it determines the next item in the collection and sets the position.

If there are more items, the state machine goes into the suspended state. If there are no more items, it goes into the after state, where it remains. Figure 20-12 shows the state machine.

Figure 20-12. An iterator state machine

536

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