Добавить в цитаты Настройки чтения

Страница 484 из 502

<b>class ItrDemo3 {</b>

<b>  static void Main() {</b>

<b>    MyClass mc = new MyClass();</b>

<b>    foreach (char ch in mc)</b>

<b>      Console.Write(ch + &quot; &quot;);</b>

<b>    Console.WriteLine();</b>

<b>  }</b>

<b>}</b>

Эта программа дает следующий результат.

<b>A B C D E F G H I J</b>

В итераторе допускается применение нескольких операторов yield. Но каждый такой оператор должен возвращать следующий элемент в коллекции. В качестве примера рассмотрим следующую программу.

<b>// Пример применения нескольких операторов yield.</b>

<b>using System;</b>

<b>using System.Collections;</b>

<b>class MyClass {</b>

<b>  // Этот итератор возвращает буквы А, В, С, D и Е.</b>

<b>  public IEnumerator GetEnumerator() {</b>

<b>    yield return 'A';</b>

<b>    yield return 'B';</b>

<b>    yield return 'C';</b>

<b>    yield return 'D';</b>

<b>    yield return 'E';</b>

<b>  }</b>

<b>}</b>

<b>class ItrDemo5 {</b>

<b>  static void Main() {</b>

<b>    MyClass mc = new MyClass();</b>

<b>    foreach (char ch in mc)</b>

<b>      Console.Write(ch + &quot; &quot;);</b>

<b>    Console.WriteLine();</b>

<b>  }</b>

<b>}</b>

Ниже приведен результата выполнения этой программы.

<b>А В С D Е</b>

В данной программе внутри метода GetEnumerator() выполняются пять операторов yield. Следует особо подчеркнуть, что они выполняются по очереди и каждый раз, когда из коллекции получается очередной элемент. Таким образом, на каждом шаге цикла foreach в методе Main() возвращается только один символ.

В приведенных выше примерах был продемонстрирован простейший способ реализации итератора. Но ему имеется альтернатива в виде именованного итератора. В данном случае создается метод, оператор или аксессор, возвращающий ссылку на

объект типа IEnumerable. Именно этот объект используется в коде для предоставления итератора. Именованный итератор представляет собой метод, общая форма которого приведена ниже:

<b>public IEnumerable имя_итератора (список_параметров) {</b>

<b>  // ...</b>

<b>  yield return obj;</b>

<b>}</b>

где имя_итератора обозначает конкретное имя метода; список_параметров — от нуля до нескольких параметров, передаваемых методу итератора; obj — следующий объект, возвращаемый итератором. Как только именованный итератор будет создан, его можно использовать везде, где он требуется, например для управления циклом foreach.

Именованные итераторы оказываются весьма полезными в некоторых ситуациях, поскольку они позволяют передавать аргументы итератору, управляющему процессом получения конкретных элементов из коллекции. Например, итератору можно передать начальный и конечный пределы совокупности элементов, возвращаемых из коллекции итератором. Эту форму итератора можно перегрузить, расширив ее функциональные возможности. В приведенном ниже примере программы демонстрируются два способа применения именованного итератора для получения элементов коллекции. В одном случае элементы перечисляются в заданных начальном и конечном пределах, а в другом — элементы перечисляются с начала последовательности и до указанного конечного предела.

<b>// Использовать именованные итераторы.</b>

<b>using System;</b>

<b>using System.Collections;</b>

<b>class MyClass {</b>

<b>  char ch = 'A';</b>

<b>  // Этот итератор возвращает буквы английского алфавита,</b>

<b>  // начиная с буквы А и кончая указанным конечным пределом</b>

<b>  public IEnumerable MyItr(int end) {</b>

<b>    for (int i = 0; i &lt; end; i++)</b>

<b>      yield return (char)(ch + i);</b>

<b>  }</b>

<b>  // Этот итератор возвращает буквы в заданных пределах</b>

<b>  public IEnumerable MyItr(int begin, int end) {</b>

<b>    for (int i = begin; i &lt; end; i++)</b>

<b>      yield return (char)(ch + i);</b>

<b>  }</b>

<b>}</b>

<b>class ItrDemo4 {</b>

<b>  static void Main() {</b>