Итератор, перебирающий 4 заданные строки

class My : IEnumerable

{

public IEnumerator GetEnumerator()

{

yield return "one";

yield return "two";

yield return "three";

yield return "ААА!!!";

}

}

class Program

{

static void Main(string[] args)

{

foreach (string s in new My()) Console.WriteLine(s);

Console.ReadKey(); } }

//Итератор, перебирающий значения в заданном диапазоне (От 1 до 5)

class Program

{

public static IEnumerable Count(int from, int to)

{

from =1;

while (from <= to) yield return from++;

}

static void Main(string[] args)

{

foreach (int i in Count(1,5)) Console.WriteLine(i);

Console.ReadKey(); } }

Преимущество использования итераторов заключается в том, что для одного и того же класса можно задать различный порядок перебора элементов.

Модернизируем пример с массивом монстров и демонов, добавив в код программы две дополнительные стратегии перебора элементов класса Mas_Monster- перебор в обратном порядке и выборка только тех объектов, которые являются экземплярами класса Monster (для этого используется метод получения типа объекта GetType()).

class Monster {…}

class Daemon : Monster {…}

class Mas_Monster : IEnumerable

{

Monster[] mas;

int n;

public Mas_Monster()

{

mas = new Monster[10];

n = 0;

}

public IEnumerator GetEnumerator()

{

for (int i = 0; i < n; i++) yield return mas[i];

}

Перебор в обратном порядке!!!

public IEnumerable Backwards()

{

for (int i = n-1; i >= 0; i--) yield return mas[i];

}

Перебор только монстров!!!

public IEnumerable MonsterOnly()

{

for (int i = 0; i < n; i++)

Метод GetType().Name возвращает имя типа

if (mas [i].GetType().Name=="Monster")

yield return mas[i];

}

public void Add(Monster m)

{

if (n >= 10) return;

mas[n] = m;

n++;

}

}

class Program

{

static void Main(string[] args)

{

Mas_Monster m = new Mas_Monster();

m.Add(new Monster(10, 10, "Вася"));

m.Add(new Daemon (10, 10, "Вася", 5));

Console.WriteLine(" Все монстры и демоны ");

foreach (Monster x in m)

x.Passport();

Console.WriteLine(" Все монстры и демоны в обратном порядке их следования в массиве ");

foreach (Monster x in m.Backwards())

x.Passport();

Console.WriteLine(" Только монстры! ");

foreach (Monster x in m.MonsterOnly())

x.Passport();

Console.ReadKey(); } }

Блок итератора синтаксически представляет собой обычный блок и может использоваться в теле метода, операции, части свойства get, если соответствующее возвращаемое значение имеет тип IEnumerable или IEnumerator. В теле блока итератора могут встречаться две конструкции:

Yield return формирует значение, выдаваемое на очередной итерации

Yield break – завершение итерации

Ключевое слово yield имеет специальное значение для компилятора только в таких конструкциях.

Код блока итератора выполняется не так, как обычные блоки. Компилятор формирует объект-перечислитель, при вызове метода MoveNext() которого выполняется код блока итератора, выдающий очередное значение с помощью слова yield. Следующий вызов метода MoveNext() объекта-перечислителя возобнавляет выполнение блока итератора с момента, на которм он был приостановлен в предыдущий раз.

Наши рекомендации