Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OSISP Part 3.DOC
Скачиваний:
42
Добавлен:
11.05.2015
Размер:
360.45 Кб
Скачать
  1. Итераторы в среде .Net. Создание и использование итераторов.

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

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

Итераторы в .NET Framework называются 'перечислителями' (enumerators) и представлены интерфейсом IEnumerator. IEnumerator реализует метод MoveNext(), который переходит к следующему элементу и указывает, достигнут ли конец коллекции; свойство Current служит для получения значения указываемого элемента; дополнительный метод Reset() возвращает перечислитель на его исходную позицию. Перечислитель первоначально указывает на специальное значение перед первым элементом, поэтому вызов MoveNext() необходим для начала итерации.

Перечислители обычно передаются вызовом метода GetEnumerator() объекта, реализующего интерфейс IEnumerable. Классы контейнеров обычно реализуют этот интерфейс. Тем не менее, выражение foreach в языке C# может оперировать любым объектом, поддерживающим подобный метод, даже если он не реализует IEnumerable. Оба интерфейса были расширены в обобщенных версиях .NET 2.0.

// 'явная' версия

IEnumerator<MyType> iter = list.GetEnumerator();

while (iter.MoveNext())

Console.WriteLine(iter.Current);

// 'неявная' версия

foreach (MyType value in list)

Console.WriteLine(value);

C# 2.0 также поддерживает генераторы: метод, объявляемый как возвращаемый IEnumerator (или IEnumerable), но использующий выражение «yield return» (гибкое возвращение) для создания последовательности элементов вместо возвращения сущности объекта, будет превращен компилятором в новый класс, реализующий соответствующий интерфейс.

Шаблон проектирования «Итератор» предназначен для последовательного доступа ко всем элементам коллекции (агрегата), не раскрывая ее внутренней структуры. Это один из классических шаблонов проектирования.

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

Для реализации итератора на языке C# нужно выполнить одно из двух условий. Во-первых, вы можете просто реализовать интерфейс IEnumerable или его «обобщенный» вариант – IEnumerable<T> (*), во-вторых, ваша коллекция может просто содержать метод GetEnumerable, который, в свою очередь возвратит сущность, содержащую свойство Current и метод MoveNext.

Давайте начнем с менее распространенного варианта, который основан не на реализации интерфейсов IEnumerable или IEnumerable<T>, а на соответствии кода приведенному выше шаблону (реализация итератора с помощью одного из интерфейсов IEnumerable является аналогичной, просто хочется подчеркнуть, что реализация интерфейса IEnumerable не является обязательной).

Итератор — метод доступа get или оператор, выполняющий настраиваемую итерацию класса массива или коллекции с помощью ключевого слова yield. При использовании оператора return ключевого слова yield элемент в исходной последовательности немедленно возвращается вызывающему объекту до того, как будет получен доступ к следующему элементу. Хотя итератор создается как метод, компилятор переводит его во вложенный класс, который фактически является конечным автоматом. Данный класс отслеживает положения итератора, пока в клиентском коде выполняется цикл foreach.

Итератор вызывается из клиентского кода с помощью оператора foreach. Например, можно создать итератор для класса, возвращающего элементы в обратном порядке или выполняющего операцию над каждым элементом перед тем, как итератор возвратит его. При создании итератора для класса или структуры реализация всего интерфейса IEnumerator не требуется. Когда компилятор обнаруживает итератор, он автоматически создает методы Current, MoveNext и Dispose интерфейса IEnumerator или IEnumerator<T>.

Итератор — это раздел кода, возвращающий упорядоченную последовательность значений одинакового типа.

Итератор может использоваться в качестве основной части метода, оператора или метода доступа get.

В коде итератора для возвращения всех элементов по очереди используется оператор yield return.yield break завершает итерацию.

В классе можно реализовать несколько итераторов. Каждый итератор должен иметь уникальное имя, как и любой член класса, и может вызываться клиентским кодом в операторе foreach: foreach(int x in SampleClass.Iterator2){}.

Тип возвращаемого итератором значения должен быть IEnumerable, IEnumerator, IEnumerable<T> или IEnumerator<T>.

Итераторы используются для обеспечения отложенного выполнения в запросах LINQ.

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

Итераторы также удобно использовать с классами коллекций, так как это обеспечивает простой способ итерации сложных структур данных, например двоичных деревьев.

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