- •Содержание
- •Введение
- •Коллекции в .Net
- •Виды коллекций
- •Типы коллекций
- •Интерфейсы, используемые коллекциями
- •Необобщенные коллекции
- •Обобщенные коллекции
- •Основные обобщенные коллекции
- •Параллельные коллекции
- •Специальные и наблюдаемые коллекции
- •Специальные коллекции
- •Наблюдаемые коллекции
- •Битовые коллекции
- •Класс BitArray
- •Структура BitVector32
- •Реализация интерфейса iComparable
- •Реализация интерфейса iComparer
- •Перечислители
- •Применение обычного перечислителя
- •Применение перечислителя типа iDictionaryEnumerator
- •Реализация интерфейсов iEnumerable и iEnumerator
- •Итераторы и оператор yield
- •Именованный итератор
- •Заключение
- •Список использованных источников
- •Приложение а (обязательное) Листинги и результаты работы программ
Итераторы и оператор 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]
