Getenumerator c как реализовать
Перейти к содержимому

Getenumerator c как реализовать

Getenumerator c как реализовать

Как мы увидели, основной для большинства коллекций является реализация интерфейсов IEnumerable и IEnumerator. Благодаря такой реализации мы можем перебирать объекты в цикле foreach :

Перебираемая коллекция должна реализовать интерфейс IEnumerable.

Интерфейс IEnumerable имеет метод, возвращающий ссылку на другой интерфейс — перечислитель:

А интерфейс IEnumerator определяет функционал для перебора внутренних объектов в контейнере:

Метод MoveNext() перемещает указатель на текущий элемент на следующую позицию в последовательности. Если последовательность еще не закончилась, то возвращает true. Если же последовательность закончилась, то возвращается false.

Свойство Current возвращает объект в последовательности, на который указывает указатель.

Метод Reset() сбрасывает указатель позиции в начальное положение.

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

Например, без использования цикла foreach перебирем массив с помощью интерфейса IEnumerator:

Реализация IEnumerable и IEnumerator

Рассмотрим простешую реализацию IEnumerable на примере:

В данном случае класс Week, который представляет неделю и хранит все дни недели, реализует интерфейс IEnumerable. Однако в данном случае мы поступили очень просто — вместо реализации IEnumerator мы просто возвращаем в методе GetEnumerator объект IEnumerator для массива.

Благодаря этому мы можем перебрать все дни недели в цикле foreach.

В то же время стоит отметить, что для перебора коллекции через foreach в принципе необязательно реализовать интерфейс IEnumerable. Достаточно в классе определить публичный метод GetEnumerator , который бы возвращал объект IEnumerator. Например:

Однако это было довольно просто — мы просто используем уже готовый перчислитель массива. Однако, возможно, потребуется задать свою собственную логику перебора объектов. Для этого реализуем интерфейс IEnumerator :

Здесь теперь класс Week использует не встроенный перечислитель, а WeekEnumerator, который реализует IEnumerator.

Ключевой момент при реализации перечислителя — перемещения указателя на элемент. В классе WeekEnumerator для хранения текущей позиции определена переменная position. Следует учитывать, что в самом начале (в исходном состоянии) указатель должен указывать на позицию условно перед первым элементом. Когда будет производиться цикл foreach, то данный цикл вначале вызывает метод MoveNext и фактически перемещает указатель на одну позицию в перед и только затем обращается к свойству Current для получения элемента в текущей позиции.

Затем в программе мы можем аналогичным образом перебирать объект Week с помощью цикла foreach:

Обобщенная версия IEnumerator

В примерах выше использовались необобщенные версии интерфейсов, однако мы также можем использовать их обобщенные двойники:

В данном случае реализуем интерфейс IEnumerator<string> , соответственно в свойстве Current нам надо возвратить объект string. В этом случае при переборе в цикле foreach перебираемые объекты будут автоматически представлять тип string :

IEnumerable<T>.Get Enumerator Метод

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Возвращает перечислитель, выполняющий перебор элементов в коллекции.

Возвращаемое значение

Перечислитель, который можно использовать для итерации по коллекции.

Примеры

В следующем примере показано, как реализовать IEnumerable<T> интерфейс и использовать ее для создания запроса LINQ. При реализации IEnumerable<T>необходимо также реализовать IEnumerator<T> или только для C# можно использовать ключевое слово yield . Реализация IEnumerator<T> также требует IDisposable реализации, которая будет отображаться в этом примере.

Комментарии

Возвращенный IEnumerator<T> объект позволяет выполнять итерацию по коллекции путем предоставления Current свойства. Перечислители можно использовать для чтения данных в коллекции, но не для изменения коллекции.

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

Current возвращает один и тот же объект, пока MoveNext не будет снова вызван как MoveNext набор для Current следующего элемента.

Если MoveNext передает конец коллекции, перечислитель позиционируется после последнего элемента в коллекции и MoveNext возвращает . false Если перечислитель находится в этой позиции, последующие вызовы также MoveNext возвращаются false . Если последний возвращенный false вызов MoveNext не Current определен. Значение свойства Current не может быть повторно задано первому элементу коллекции; вместо этого следует создать новый экземпляр перечислителя.

Если изменения вносятся в коллекцию, например добавление, изменение или удаление элементов, поведение перечислителя не определено.

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

IEnumerable. Get Enumerator Метод

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Возвращает перечислитель, который осуществляет итерацию по коллекции.

Возвращаемое значение

Объект IEnumerator, который используется для прохода по коллекции.

Примеры

В следующем примере кода демонстрируется реализация IEnumerable интерфейсов для пользовательской коллекции. В этом примере GetEnumerator явно не вызывается, но реализуется для поддержки использования foreach ( For Each в Visual Basic). Этот пример кода является частью более крупного примера для IEnumerable интерфейса.

Комментарии

Инструкция foreach языка C# ( For Each в Visual Basic) позволяет скрыть сложный механизм перечислителей. Поэтому рекомендуется вместо непосредственного использования перечислителя применять ключевое слово foreach .

Перечислители могут использоваться для чтения данных в коллекции, но не для ее изменения.

Изначально перечислитель располагается перед первым элементом коллекции. Метод Reset также возвращает перечислитель в эту позицию. В этой позиции Current свойство не определено. Поэтому необходимо вызвать MoveNext метод для продвижения перечислителя к первому элементу коллекции, прежде чем считывать значение Current.

Current возвращает тот же объект, пока не будет вызван метод MoveNext или Reset. MoveNext задает Current в качестве значения для следующего элемента.

Если MoveNext передает конец коллекции, перечислитель позиционируется после последнего элемента в коллекции и MoveNext возвращает . false Если перечислитель находится в этой позиции, последующие вызовы также MoveNext возвращаются false . Если последний вызов для MoveNext возврата не false Current определен. Чтобы снова задать в качестве значения свойства Current первый элемент коллекции, можно последовательно вызвать методы Reset иMoveNext.

Если изменения вносятся в коллекцию, например добавление, изменение или удаление элементов, поведение перечислителя не определено.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *