C# 4.0 полное руководство - 2011
Шрифт:
В приведенных выше примерах был продемонстрирован простейший способ реализации итератора. Но ему имеется альтернатива в виде именованного итератора. В данном случае создается метод, оператор или аксессор, возвращающий ссылку на
объект типа I Enumerable. Именно этот объект используется в коде для предоставления итератора. Именованный итератор представляет собой метод, общая форма которого приведена ниже:
public IEnumerable имя_итератора (список_параметров) {
// ...
yield return obj;
}
где имя_итератора обозначает
foreach.
Именованные итераторы оказываются весьма полезными в некоторых ситуациях, поскольку они позволяют передавать аргументы итератору, управляющему процессом получения конкретных элементов из коллекции. Например, итератору можно передать начальный и конечный пределы совокупности элементов, возвращаемых из коллекции итератором. Эту форму итератора можно перегрузить, расширив ее функциональные возможности. В приведенном ниже примере программы демонстрируются два способа применения именованного итератора для получения элементов коллекции. В одном случае элементы перечисляются в заданных начальном и конечном пределах, а в другом — элементы перечисляются с начала последовательности и до указанного конечного предела.
// Использовать именованные итераторы.
using System;
using System.Collections;
class MyClass { char ch = 'A';
// Этот итератор возвращает буквы английского алфавита,
}
}
class ItrDemo4 {
static void Main {
MyClass me = new MyClass ;
Console.WriteLine("Возвратить по очереди первые 7 букв:"); foreach(char ch in mc.MyItr(7))
Console.Write(ch + " ");
Console .WriteLine (lf\nlf) ;
Console.WriteLine("Возвратить по очереди буквы от F до L:"); foreach(char ch in mc.Myltr(5, 12))
Console.Write(ch + " ");
Console.WriteLine;
}
}
Эта программа дает следующий результат.
Возвратить по очереди первые 7 букв:
А В С D Е F G
Возвратить по очереди буквы от F до L:
F G Н I J К L
Создание обобщенного итератора
В приведенных выше примерах применялись необобщенные итераторы, но, конечно,
// Простой пример обобщенного итератора, using System;
using System.Collections.Generic;
class MyClass<T> {
T [ ] array;
public MyClass(T[] a) { array = a;
}
// Этот итератор возвращает символы из массива chrs. public IEnumetator<T> GetEnumerator {
foreach(T obj in array) yield return obj;
}
}
class GenericItrDemo { static void Main {
int [ ] nums ={4, 3, 6, 4, 7, 9 };
MyClass<int> me = new MyClass<int>(nums);
foreach(int x in me)
Console.Write(x + " ");
Console.WriteLine;
bool[] bVals = { true, true, false, true };
MyClass<bool> mc2 = new MyClass<bool>(bVals);
foreach(bool b in mc2)
Console.Write(b + " ");
Console.WriteLine ;
}
}
Вот к какому результату приводит выполнение этой программы.
4 3 6 4 7 9
True True False True
В данном примере массив, состоящий из возвращаемых по очереди объектов, передается конструктору класса MyClass. Тип этого массива указывает в качестве аргумента типа в конструкторе класса MyClass.
Метод GetEnumerator оперирует данными обобщенного типа Т и возвращает перечислитель типа IEnumerator<T>. Следовательно, итератор, определенный в классе MyClass, способен перечислять данные любого типа.
Инициализаторы коллекций
В С# имеется специальное средство, называемое инициализатором коллекции и упрощающее инициализацию некоторых коллекций. Вместо того чтобы явно вызывать метод Add , при создании коллекции можно указать список инициализаторов. После этого компилятор организует автоматические вызовы метода Add , используя значения из этого списка. Синтаксис в данном случае ничем не отличается от инициализации массива. Обратимся к следующему примеру, в котором создается коллекция типа List<char>, инициализируемая символами С, А, Е, В, D и F.