Enumerando uma Coleção

O .NET Framework fornece enumeradores como uma maneira fácil para iterar através de uma coleção Enumeradores apenas leem os dados na coleção; eles não podem ser usados para modificar a coleção subjacente.

Algumas linguagens fornecem uma instrução que oculta a complexidade de usar enumeradores diretamente. A instrução foreach do C#, a instrução for each do C++ e a instrução For Each do Visual Basic usam enumeradores.

Sobre Enumerators

Um enumerador mescla uma coleção para que os membros possam ser acessados sequencialmente. Classes de Coleções diferentes podem ter diferentes sequências. Por exemplo, um enumerador para um ArrayList preserva a ordem no qual os elementos são inseridos na coleção, enquanto um enumerador para um Hashtable exibe os elementos de acordo com o código hash do elemento.

Cada enumerador baseia-se na interface IEnumerator ou na interface genérica IEnumerator<T>, que requer os seguintes membros:

  • A propriedade Current aponta para o atual membro na coleção.

  • A propriedade MoveNext move o enumerador para o próximo membro na coleção.

  • A propriedade Reset move o enumerador de volta para o início da coleção. Current é posicionado antes do primeiro elemento. Reset não está disponível na interface genérica IEnumerator<T>.

Comportamento de um enumerador

Inicialmente, o enumerador está posicionado antes do primeiro elemento na coleção. Reset também traz o enumerador de volta para essa posição. Nesta posição, Current é indefinido. Portanto, você deve chamar MoveNext para avançar o enumerador para o primeiro elemento da coleção antes de ler o valor de Current.

Current retorna o mesmo objeto até que MoveNext ou Reset seja chamado. MoveNext define Current para o próximo elemento.

Se MoveNext passa o final da coleção, o enumerador está posicionado após o último elemento na coleção e MoveNext retorna false. Quando o enumerador está nessa posição, chamadas subsequentes para MoveNext também retornarão false. Se a última chamada a MoveNext retornou false, Current é indefinido.

Em coleções não genéricas, você pode chamar Reset seguido de MoveNext para mover o enumerador novamente para o início da coleção.

Em coleções genéricas, você não pode definir Current para o primeiro elemento da coleção novamente; você deve criar uma nova instância de enumerador em vez disso.

Um enumerador permanece válido, desde que a coleção permaneça inalterada. Se as alterações forem feitas à coleção, tais como adicionar, modificar ou excluir elementos, o enumerador é irrecuperavemente invalidado e seu comportamento é indefinido.

O enumerador não tem acesso exclusivo à coleção; Portanto, enumerando através de uma coleção intrinsecamente não é um procedimento de thread-safe. Para garantir segurança de segmentos durante enumeração, você pode bloquear a coleção durante toda a enumeração. Para permitir que a coleção para ser acessado por vários threads de leitura e gravação, você deve implementar sua própria sincronização ou use uma das classes de coleção de thread-safe, na System.Collections.Concurrent namespace. O System.Collections.Concurrent.ConcurrentQueue<T> e System.Collections.Concurrent.ConcurrentStack<T> classes um instantâneo dos elementos antes de enumerá-los para evitar mutações à coleção em outro segmento. O System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> classe não tirar um instantâneo.

O System.Collections.Concurrent.BlockingCollection<T> classe fornece um método enumerador chamado GetConsumingEnumerable que sofre mutações da coleção, removendo os itens da coleção como ele enumera.

Consulte também

Referência

IEnumerator

IEnumerator<T>

IDictionaryEnumerator

IEnumerable

IEnumerable<T>

Conceitos

Criando e Manipulando Coleções

Coleções de thread-Safe.