Primero déjeme mostrarle un código de demostración. La clase de la lista viene del espacio de nombres System.Collections.Generic .
Creamos una lista.
12345678910List<string> toBeIterated =newList<string ];();toBeIterated.Add("Programming");toBeIterated.Add("is");toBeIterated. Add("really");toBeIterated.Add("fun");toBeIterated.Add("if");toBeIterated.Add("you");toBeIterated.Add("do");toBeIterated.Add("it");toBeIterated.Add("right");
csharp
Podemos convertir esta lista en un generador de forma muy sencilla.
1IEnumerable<string;iEnumerableOftoBeiterated =(IEnumerable<string;<)toBeIterated;
csharp
El uso de un bucle de proa nos permitirá recorrer la lista.
1234foreach(elemento de cadena en iEnumerableOftoBeiterated){ Console.WriteLine(elemento);}
csharp
La ejecución del código nos dará el siguiente resultado.
123456789La programación es realmente unificadora. bashEste fue el enfoque del generador. Ahora veamos cómo podemos usar el enfoque del iterador.
Vamos a convertir nuestra lista.
1IEnumerador<string>; iEnumeradorOftoBeiterated = toBeiterated.GetEnumerator();csharp
Como se mencionó anteriormente, GetEnumerator() funcionará porque la clase List del espacio de nombres genérico implementa la interfaz IEnumerator. Sin embargo, el foreach no puede ser usado. Necesitamos un bucle de tiempo para esto.
1234while(iEnumeratorOftoBeiterated.MoveNext()){ Console.WriteLine($"El valor actual es: {iEnumeratorOftoBeiterated.Current}");}csharp
La ejecución del código anterior nos dará lo siguiente.
123456789El valor actual es: ProgramaciónEl valor actual es: esEl valor actual es: realmenteEl valor actual es: funEl valor actual es: ifEl valor actual es: youEl valor actual es: doEl valor actual es: itEl valor actual es: rightbash
Tenga en cuenta que no hay ninguna declaración de ruptura, pero no entra en el modo infinito.
Nota: Ambos enfoques tienen el mismo objetivo: permitir al programador atravesar un contenedor, en nuestro caso una lista. Sin embargo, cuando usamos el enfoque IEnumerador, sólo funciona si se llama a la función MoveNext(). La principal diferencia entre IEnumerable y IEnumerator es que esta última mantiene el estado actual del cursor.
Un consejo: Si quieres pasar secuencialmente por una colección, debes usar la interfaz IEnumerable. Si quieres mantener la posición del cursor y pasarlo entre funciones, debes usar el IENumerador.
Veamos un ejemplo práctico. Nos gustaría crear una pequeña aplicación que pueda procesar los números de manera diferente dependiendo de si son pares o impares. IEnumerator nos proporciona una elegante solución que implica dos métodos estáticos.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667usando el sistema;usando el sistema. Hilo de rosca;usando System.Collections.Generic;generadores de espacios de nombresNitros{classProgram{estaticevitalProcessor(IEnumerator<int;i){si(i. Current ==0){ Console.WriteLine("La lista fue procesada, saliendo!"); Thread.Sleep(10); i.Dispose();}elseif(i.Current %2!=0){ Console.WriteLine("El número es ODD, llamando al procesador. ");OddProcessor(i);}elseif(i.Current %2==0){ Console.WriteLine($"Procesando par: {i.Current}"); Console.WriteLine("¡Número par procesado! "); i.MoveNext();EvenProcessor(i);}else{ i.Dispose();}}estaticvoidOddProcessor(IEnumerator<int> i){if(i.Current ==0){ Console. WriteLine("La lista fue procesada, saliendo!"); Thread.Sleep(5); i.Dispose();}elseif(i.Current %2==0){ Console.WriteLine("El número es EVEN, llamando al procesador. ");EvenProcessor(i);}elseif(i.Current %2!=0){ Console.WriteLine($"Procesando impar: {i.Current}"); Console.WriteLine("¡Número impar procesado!"); i. MoveNext();OddProcessor(i);}else{ i.Dispose();}}}estaticvoidMain(string[] args){ List<int> myList =newList<int;};(10);for(int i =1; i <=20; i++){ myList.Add(i);} IEnumerador<int;}; miListEnum = miLista.GetEnumerator(); miListEnum.MoveNext();OddProcessor(miListEnum); Console.ReadKey();}}csharp
Cuando ejecutamos este código, lo siguiente está en nuestra consola.
123456789101112131415161718192021222324252627282930Procesando impares: 1Número impar procesado! El número es EVEN, llamando al procesador.Procesando pares: 2Número impar procesado! El número es ODD, llamando al procesador.Procesando impares: 3Número impar procesado! El número es EVEN, llamando al procesador.Procesando pares: 4Número impar procesado! El número es ODD, llamando al procesador.Procesando impares: 5Número impar procesado! El número es par, llamando al procesador. Par: 6 Pares procesados. El número es ODD, llamando al procesador. Pares: 7 Pares procesados. El número es par, llamando al procesador. Pares procesados. 8 Pares procesados. El número es ODD, llamando al procesador. Pares procesados. 9 Pares procesados. El número es par, llamando al procesador. Pares procesados. 10 Pares procesados. La lista fue procesada, saliendo. bash¿Qué pasa aquí? Tenemos una lista con números del 1 al 20, y esta lista se convierte en un iterador con la siguiente declaración.
1IEnumerador<int;;myListEnum = myList.GetEnumerator();csharp
Esto es necesario porque tenemos dos métodos estáticos, Procesador Par y Procesador Impar. Ambos toman un argumento IEnumerador, que es la posición actual de nuestro cursor. Esta solución no utiliza ningún bucle. Funciona simplemente a través de la magia de los iteradores. Nuestra lista es de sólo 10 elementos, y si el número es parejo la función apropiada lo procesará. Lo mismo ocurre con los números impares. La tecla aquí es la i.Current y el hecho de que la posición del cursor se mantiene.