Поделиться через


Перечисление коллекции

В качестве простого способа перебора элементов коллекции платформа .NET Framework позволяет использовать механизм перечислителей. Перечислители могут лишь читать данные в коллекции; они не могут быть использованы для изменения коллекции, с которой они работают.

В некоторых языках существуют операторы, скрывающие сложности, связанные с непосредственным использованием перечислителей. Перечислители используются оператором языка C# foreach, оператором языка C++ for each и оператором языка Visual Basic For Each.

О перечислителях

Коллекции воспринимаются перечислителями таким образом, что доступ к их элементам может осуществляться последовательно. Различные классы коллекций могут иметь различный порядок следования элементов. Например, перечислитель для класса ArrayList сохраняет порядок, в котором элементы были введены в коллекцию, в то время как перечислитель для класса Hashtable перебирает элементы в соответствии с их хэш-кодом.

Все перечислители основаны на интерфейсе IEnumerator или на универсальном интерфейсе IEnumerator<T>, для чего им необходимо иметь перечисленные ниже члены.

  • Свойство Current указывает на текущий элемент коллекции.

  • Свойство MoveNext перемещает перечислитель к следующему элементу коллекции.

  • Свойство Reset перемещает перечислитель в начало коллекции. Свойство Current при этом указывает на положение перед первым элементом. В универсальном интерфейсе IEnumerator<T> свойство Reset отсутствует.

Поведение перечислителей

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

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

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

В неуниверсальных коллекциях для перемещения перечислителя обратно в начало можно вызвать Reset, а затем — MoveNext.

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

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

Перечислитель не имеет монопольного доступа к коллекции, поэтому внутреннее перечисление коллекции в многопоточных операциях не является потокобезопасным. Чтобы гарантировать потокобезопасность при перечислении, можно заблокировать коллекцию на все время выполнения процедуры перечисления. Чтобы разрешить доступ к коллекции для чтения и записи из нескольких потоков, необходимо реализовать собственный механизм синхронизации или использовать один из классов потокобезопасных коллекций в пространстве имен System.Collections.Concurrent. Класс System.Collections.Concurrent.ConcurrentQueue<T> и класс System.Collections.Concurrent.ConcurrentStack<T> для предупреждения внесения изменений коллекций другим потоком создают снимок элементов перед их перечислением. Класс System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> не выполняет создание снимка.

Класс System.Collections.Concurrent.BlockingCollection<T> предоставляет метод перечислителя с именем GetConsumingEnumerable, который изменяет коллекцию путем удаления элементов из их перечисления.

См. также

Ссылки

IEnumerator

IEnumerator<T>

IDictionaryEnumerator

IEnumerable

IEnumerable<T>

Основные понятия

Управление коллекциями и их создание

Потокобезопасные коллекции