c# enumeration

list ienumerable c#



IEnumerable, IEnumerator vs foreach, cuándo usar qué (3)

Esta pregunta ya tiene una respuesta aquí:

Pasaba por IEnumerable e IEnumerator, pero no pude obtener un punto con claridad ... si tenemos que buscar, ¿por qué necesitamos estas dos interfaces? ¿Hay algún escenario en el que tengamos que usar interfaces? Si es así, entonces alguien puede explicarlo con un ejemplo. Cualquier sugerencia y comentario son bienvenidos. Gracias.


Lo que Jon dijo.

  • IEnumerable o IEnumerable<T> : al implementar esto, un objeto indica que puede proporcionarle un iterador que puede usar para recorrer la secuencia / colección / conjunto
  • IEnumerator o IEnumerator<T> : si llama al método GetEnumerator definido en la interfaz anterior, obtiene un objeto iterador como referencia de IEnumerator. Esto le permite llamar a MoveNext () y obtener el objeto actual.
  • foreach : es una construcción / fachada de C # en el sentido de que no necesitas saber cómo funciona debajo del capó. Obtiene internamente el iterador y le llama a los métodos correctos para que usted se concentre en lo que quiere hacer con cada elemento (el contenido del bloque foreach). La mayoría de las veces, solo necesitaría una persona a menos que esté implementando su propio tipo o iteración personalizada, en cuyo caso tendrá que conocer las primeras 2 interfaces.

Tenga en cuenta que no tiene que implementar IEnumerator y sus variantes para usar foreach - IIRC, todo lo que necesita es un método GetEnumerator () que devuelve un objeto que tiene un método MoveNext () que devuelve un bool, y una propiedad Current que regresa un objeto. No es necesario utilizar IEnumerator y IEnumerable, aunque en general es una muy buena idea hacerlo. Vea here para más información.


foreach utiliza las interfaces en muchos casos. Necesita las interfaces si desea implementar una secuencia que foreach pueda usar. (Los bloques de iteradores generalmente hacen que esta tarea de implementación sea muy simple).

Sin embargo, solo ocasionalmente puede ser útil utilizar los iteradores directamente. Un buen ejemplo es cuando se intenta "emparejar" dos secuencias diferentes. Por ejemplo, suponga que recibe dos secuencias: una de nombres, una de edades y desea imprimir las dos juntas. Usted podría escribir:

static void PrintNamesAndAges(IEnumerable<string> names, IEnumerable<int> ages) { using (IEnumerator<int> ageIterator = ages.GetEnumerator()) { foreach (string name in names) { if (!ageIterator.MoveNext()) { throw new ArgumentException("Not enough ages"); } Console.WriteLine("{0} is {1} years old", name, ageIterator.Current); } if (ageIterator.MoveNext()) { throw new ArgumentException("Not enough names"); } } }

Del mismo modo, puede ser útil usar el iterador si desea tratar (decir) el primer elemento de forma diferente al resto:

public T Max<T>(IEnumerable<T> items) { Comparer<T> comparer = Comparer<T>.Default; using (IEnumerator<T> iterator = items.GetEnumerator()) { if (!iterator.MoveNext()) { throw new InvalidOperationException("No elements"); } T currentMax = iterator.Current; // Now we''ve got an initial value, loop over the rest while (iterator.MoveNext()) { T candidate = iterator.Current; if (comparer.Compare(candidate, currentMax) > 0) { currentMax = candidate; } } return currentMax; } }

Ahora, si está interesado en la diferencia entre IEnumerator<T> e IEnumerable<T> , puede pensar en términos de la base de datos: piense en IEnumerable<T> como una tabla, y en IEnumerator<T> como un cursor . Puede pedir a una tabla que le dé un nuevo cursor y puede tener varios cursores sobre la misma tabla al mismo tiempo.

Puede llevar un tiempo realmente arruinar esta diferencia, pero solo recuerda que una lista (o matriz, o lo que sea) no tiene ningún concepto de "dónde estás en la lista", sino un iterador sobre esa lista / matriz / lo que sea Tener ese poco de estado es útil.