Enumerar una colección

.NET Framework proporciona enumeradores para recorrer en iteración fácilmente por una colección. Los enumeradores sólo leen los datos de la colección; no pueden utilizarse para modificar la colección subyacente.

Algunos lenguajes proporcionan una instrucción que oculta la complejidad del uso de enumeradores directamente. La instrucción foreach de C#, la instrucción for each de C++ y la instrucción For Each de Visual Basic utilizan enumeradores.

Enumeradores

Un enumerador simplifica el uso de una colección de forma que se puede tener acceso a sus miembros secuencialmente. Diferentes clases de colecciones pueden tener diferentes secuencias. Por ejemplo, el enumerador de una colección ArrayList conserva el orden con que se introducen elementos en la colección, mientras que el de Hashtable muestra los elementos según su código hash.

Todos los enumeradores se basan en la interfaz IEnumerator o en la interfaz genérica IEnumerator<T>, que requiere los siguientes miembros:

  • La propiedad Current indica el miembro actual de la colección.

  • La propiedad MoveNext mueve el enumerador al siguiente elemento de la colección.

  • La propiedad Reset mueve el enumerador al principio de la colección. Current se coloca delante del primer elemento. Reset no está disponible en la interfaz genérica IEnumerator<T>.

Comportamiento de un enumerador

Inicialmente, el enumerador se coloca antes del primer elemento de la colección. Reset también devuelve el enumerador a esta posición. Current, por su parte, no queda definida en esta posición. Por tanto, antes de leer el valor de Current, deberá llamarse a MoveNext para hacer avanzar al enumerador hasta el primer elemento de la colección.

Current devuelve el mismo objeto hasta que se llama a MoveNext o a Reset. MoveNext establece Current en el siguiente elemento.

Si MoveNext rebasa el final de la colección, el enumerador quedará tras el último elemento y MoveNext devolverá false. Mientras el enumerador permanezca en esta posición, las llamadas a MoveNext seguirán devolviendo false. Cuando la última llamada a MoveNext haya devuelto false, Current quedará indefinida.

En colecciones no genéricas, puede llamarse a Reset seguida de MoveNext para devolver el enumerador al principio de la colección.

En colecciones no genéricas, no es posible volver a establecer Current en el primer elemento de la colección. En lugar de ello, deberá crearse una instancia de enumerador nueva.

Mientras no se modifique la colección, el enumerador seguirá siendo válido. Si se realizan cambios en la colección, como agregar, modificar o eliminar elementos, el enumerador se invalida definitivamente y su comportamiento queda sin definir.

El enumerador no tiene acceso exclusivo a la colección; por lo tanto, la enumeración a través de una colección es un procedimiento que, por naturaleza, no es seguro para la ejecución de subprocesos. Para garantizar la seguridad en la ejecución de subprocesos durante la enumeración, puede bloquear la colección durante la enumeración completa. Para permitir que varios subprocesos obtengan acceso de lectura y escritura a la colección, debe implementar su propia sincronización o utilizar una de las clases de colección seguras para subprocesos en el espacio de nombres System.Collections.Concurrent. Las clases System.Collections.Concurrent.ConcurrentStack<T> y System.Collections.Concurrent.ConcurrentQueue<T> toman una instantánea de los elementos antes de enumerarlos, para evitar mutaciones en la colección de otro subproceso. La clase System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> no toma ninguna instantánea.

La clase System.Collections.Concurrent.BlockingCollection<T> proporciona un método de enumerador llamado GetConsumingEnumerable que muta la colección quitando los elementos de la colección al enumerarlos.

Vea también

Referencia

IEnumerator

IEnumerator<T>

IDictionaryEnumerator

IEnumerable

IEnumerable<T>

Conceptos

Colecciones seguras para subprocesos

Otros recursos

Crear y manipular colecciones