Язык программирования C#9 и платформа .NET5. Страница 176
// Вручную работать с IEnumerator.IEnumerator carEnumerator = carLot.GetEnumerator();carEnumerator.MoveNext();Car myCar = (Car)i.Current;Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrentSpeed);Тем не менее, если вы предпочитаете скрыть функциональность
IEnumerable// Возвратить IEnumerator объекта массива.IEnumerator IEnumerable.GetEnumerator() => return carArray.GetEnumerator();В результате обычный пользователь объекта не обнаружит метод
GetEnumerator()GarageforeachПостроение итераторных методов с использованием ключевого слова yield
Существует альтернативный способ построения типов, которые работают с циклом
foreachforeachCustomEnumeratorWithYieldCarRadioGarageGaragepublic class Garage : IEnumerable{ ...<b> // Итераторный метод.</b> public IEnumerator GetEnumerator() { foreach (Car c in carArray) { yield return c; } }}Обратите внимание, что показанная реализация метода
GetEnumerator()foreachCaryield returnyieldforeachyield returnИтераторные методы не обязаны использовать ключевое слово
foreachpublic IEnumerator GetEnumerator(){ yield return carArray[0]; yield return carArray[1]; yield return carArray[2]; yield return carArray[3];}В этой реализации обратите внимание на то, что при каждом своем прохождении метод
GetEnumerator()carArrayGetEnumerator()foreachЗащитные конструкции с использованием локальных функций (нововведение в версии 7.0)
До первого прохода по элементам (или доступа к любому элементу) никакой код в методе
GetEnumerator()yieldMoveNext()Чтобы проверить это, модифицируйте
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()