До первого прохода по элементам (или доступа к любому элементу) никакой код в методе GetEnumerator
yield возникает условие для исключения, то оно не будет сгенерировано при первом вызове метода, а лишь во время первого вызова MoveNext.Чтобы проверить это, модифицируйте GetEnumerator
public IEnumerator GetEnumerator
{
// Исключение не сгенерируется до тех пор, пока не будет вызван
// метод MoveNext.
throw new Exception("This won't get called");
foreach (Car c in carArray)
{
yield return c;
}
}
Если функция вызывается, как показано далее, и
using System.Collections;
...
Console.WriteLine("***** Fun with the Yield Keyword *****\n");
Garage carLot = new Garage;
IEnumerator carEnumerator = carLot.GetEnumerator;
Console.ReadLine;
Код выполнится только после вызова MoveNext
GetEnumerator может иметь Iterator, который рассматривается далее.Вспомните средство локальных функций версии C# 7, представленное в главе 4; локальные функции — это закрытые функции, которые определены внутри других функций. За счет перемещения yield return
MoveNext.Приведите метод к следующему виду:
public IEnumerator GetEnumerator
{
// Это исключение сгенерируется немедленно
throw new Exception("This will get called");
return ActualImplementation;
// Локальная функция и фактическая реализация IEnumerator
IEnumerator ActualImplementation
{
foreach (Car c in carArray)
{
yield return c;
}
}
}
Ниже показан тестовый код:
Console.WriteLine("***** Fun with the Yield Keyword *****\n");
Garage carLot = new Garage;
try
{
// На этот раз возникает ошибка
var carEnumerator = carLot.GetEnumerator;
}
catch (Exception e)
{
Console.WriteLine($"Exception occurred on GetEnumerator");
}
Console.ReadLine;
В результате такого обновления метода GetEnumerator
MoveNext.Построение именованного итератора
Также интересно отметить, что ключевое слово yield
IEnumerable, а не ожидаемый совместимый с IEnumerator тип. В целях иллюстрации добавьте к типу Garage следующий метод (использующий локальную функцию для инкапсуляции функциональности итерации):public IEnumerable GetTheCars(bool returnReversed)
{
// Выполнить проверку на предмет ошибок
return ActualImplementation;
IEnumerable ActualImplementation
{
// Возвратить элементы в обратном порядке.
if (returnReversed)
{
for (int i = carArray.Length; i != 0; i--)
{
yield return carArray[i - 1];
}
}
else
{
Бьёрн Страуструп , Ирина Сергеевна Козлова , Бьерн Страуструп , Валерий Федорович Альмухаметов
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT