Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курсовая_работа_Курдюмовой_Татьяны_Игоревной_2И...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
488.66 Кб
Скачать
  1. Итераторы и оператор yield

Итератор представляет собой метод, в котором используется ключевое слово yield для перебора по коллекции или массиву. [3]

Наиболее простой способ создания итератора заключается в реализации метода GetEnumerator для интерфейса IEnumerable, например:

public System.Collections.IEnumerator GetEnumerator()

{

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

{

yield return i;

}

}

Наличие метода GetEnumerator создает тип перечисляемого типа и позволяет использовать оператор foreach statement. Если бы приведенный выше метод был частью определения класса для ListClass, то можно было бы использовать foreach для класса следующим образом [5]

static void Main()

{

ListClass listClass1 = new ListClass();

foreach (int i in listClass1)

{

System.Console.WriteLine(i);

}

}

Оператор foreach вызывает ListClass.GetEnumerator() и использует возвращенный перечислитель для итерации значений. [5]

Кроме того, можно использовать именованные итераторы в поддержку различных возможностей перебора одной и той же коллекции данных. [5]

Например, можно было бы предоставить один итератор, возвращающий элементы по возрастанию, а другой итератора, возвращающий элементы по убыванию. Итератор может также иметь параметры, позволяющие клиентам управлять всем поведением итератора или его часть. Следующий итератор реализует интерфейс IEnumerable при помощи именованного итератора SampleIterator [5]

public System.Collections.IEnumerable SampleIterator(int start, int end)

{

for (int i = start; i <= end; i++)

{

yield return i;

}

}

Именованный итератор вызывается следующим образом. [5]

ListClass test = new ListClass();

foreach (int n in test.SampleIterator(1, 10))

{

System.Console.WriteLine(n);

}

В одном итераторе можно использовать несколько операторов yield, как в следующем примере. [5]

public System.Collections.IEnumerator GetEnumerator()

{

yield return "With an iterator, ";

yield return "more than one ";

yield return "value can be returned";

yield return ".";

}

Результаты можно вывести с помощью оператора foreach. [5]

foreach (string element in new TestClass())

{

System.Console.Write(element);

}

В каждой последовательной итерации цикла foreach (или прямом вызове IEnumerator.MoveNext) следующий текст кода итератора возобновляется после оператора yield и продолжается до конца текста итератора или до оператора yield break.

Итераторы не поддерживают метод IEnumeratorReset(). Для повторной итерации сначала необходимо получить новый итератор. [5]

IEnumerator IEnumerable.GetEnumerator()

{

for (int i = 0; i < books.Length; i++)

{

yield return books[i];

}

}

Метод GetEnumerator() теперь будет являться итератором. Когда будет осуществляться перебор в объекте Library в цикле foreach, то будет идти обращение к вызову yield return books[i]. При обращении к оператору yield return будет сохраняться текущее местоположение. И когда метод foreach перейдет к следующей итерации для получения нового объекта, итератор начнет выполнения с этого местоположения. [3]

В основной программе в цикле foreach выполняется перебор, благодаря реализации итератора:

foreach (Book b in library)

{

Console.WriteLine(b.Name);

}

При реализации итератора в методе GetEnumerator() применять перебор массива в цикле for необязательно. Можно определить несколько вызовов оператора yield return, как показано в примере ниже. [3]

IEnumerator IEnumerable.GetEnumerator()

{

yield return books[0];

yield return books[1];

yield return books[2];

}

В этом случае при каждом вызове оператора yield return итератор также будет запоминать текущее местоположение и при последующих вызовах начинать с него. [3]