En cualquier lenguaje de programación hay una serie de estructuras básicas para
realizar un bucle, en esta publicación analizaremos el bucle for y el bucle foreach, y la conveniencia de usar el segundo sobre el primero, el código mostrado sera en C# (aunque debiera ser semejante en cualquier otro lenguaje).
Comencemos viendo los tipos de bucle mas comunes:
- Esta el bucle while:
1
2
3
4
| while (SeCumplaCondicion()) { } |
while (SeCumplaCondicion()) { }
Es el más básico, y se ejecutaría hasta que algo hiciera que se cumpla la condición.
- bucle while tipo dos:
1
2
3
| do { } while (SeCumplaCondicion()) |
do { } while (SeCumplaCondicion())
Garantiza que por lo menos se realiza una iteración del bucle antes de comprobar
si se cumple la sentencia, por lo demás es igual que el anterior
- El bucle for:
1
2
3
4
| for ( int i = 0; i < 10; i++) { } |
for (int i = 0; i < 10; i++) { }
Este bucle se usa para recorrer algún tipo de array, o una colección, teniendo esta
estructura
1
2
3
4
5
6
| List< string > nombres = new List< string >() { "JUAN" , "PEDRO" , "ANA" , "INES" }; for ( int i = 0; i < nombres.Count; i++) { Console.WriteLine( " Nombre :" + nombres[i]); } |
List<string> nombres = new List<string>() { "JUAN", "PEDRO", "ANA", "INES" }; for (int i = 0; i < nombres.Count; i++) { Console.WriteLine(" Nombre :" + nombres[i]); }
El resultado será algo parecido a:
- Nombre :JUAN
- Nombre :PEDRO
- Nombre :ANA
- Nombre :INES
Este bucle tiene varios problemas asociados:
lo primero es que usamos un numero para acceder a la colección, si nos fijamos nuestra
intención no es trabajar con la posición de los nombres dentro del objeto, es decir
nos da igual si es la primera o la ultima, nosotros queremos recórrelos todos en
secuencia uno a uno. Su posición para nosotros es irrelevante. Esto es importante,
por que se pierde el verdadero objetivo del código, hacer algo con todos los elementos
del array, al margen de su posición. Requiera además que ya se sepan todos los nombres
(los elementos de la colección) antes de procesar el bucle, en algunos casos no
requeríamos conocer todo el escenario antes de querer procesarlo, por ejemplo, si
estamos buscando un archivo en todo el disco duro, no sería recomendable que primero
listemos todos los archivos y luego lo recorriéramos buscando el archivo idóneo.
- El último bucle, es el bucle foreach, tiene la siguiente estructura
List<string> nombres = GenerarListaNombres();
1
2
3
4
5
6
| List< string > nombres = GenerarListaNombres(); foreach ( string nombre in nombres) { Console.WriteLine( " Nombre :" + nombre); } |
List<string> nombres = GenerarListaNombres(); foreach (string nombre in nombres) { Console.WriteLine(" Nombre :" + nombre); }
En esta forma de bucle, se elimina el uso de los índices (int i), lo que
simplifica su código y nos permite centrarnos en el objetivo real, que es recorrer
los elementos de la lista.
El hecho de que el código sea más sencillo, lo hace a su vez mas mantenibles y escalable
en un futuro.
Por otro lado el único requisito es que el elemento a recorrer implemente la interfaz
IEnumerable, lo cual nos permite realizar ajustes a como se procesan los
elementos, en este ejemplo se recorren los nombres hasta que se encuentra la palabra
"PEDRO"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public static void Ejemplo2() { foreach ( string nombre in GenerarListaNombresEnumerable()) { Console.WriteLine( " Nombre :" + nombre); if (nombre == "PEDRO" ) break ; } } public static IEnumerable< string > GenerarListaNombresEnumerable() { yield return "JUAN" ; yield return "PEDRO" ; yield return "ANA" ; yield return "INES" ; } |
public static void Ejemplo2() { foreach (string nombre in GenerarListaNombresEnumerable()) { Console.WriteLine(" Nombre :" + nombre); if (nombre == "PEDRO") break; } } public static IEnumerable<string> GenerarListaNombresEnumerable() { yield return "JUAN"; yield return "PEDRO"; yield return "ANA"; yield return "INES"; }
Esta función especial que devuelve los campos con la palabra yield, nos permite
genera la lista de nombres al mismo tiempo que se está procesando, la ventaja es
que no se generan nombres que no se van a usar (por ejemplo no se genera "ANA",
ni "INES", en caso que poníamos anteriormente, si estuviéramos buscando un archivo
por todo el disco duro, podríamos detener la búsqueda cuando encontráramos el archivos
requerido, y no tendríamos primero que localizar todo los archivos y ver si cumplen
las características que deseamos uno a uno.
Adicionalmente el listado de nombre no se puede modificar dentro de un bucle foreach,
con lo que garantiza seguridad de no alteración del listado (los objetos dentro
del listado si se puede mejorar).
Resumiendo las ventajas del bucle foreach, quedarían las siguiente:
- Código más limpio y sencillo, que expresa mejor las intenciones del codificador.
- No es necesario generar completamente los elementos a recorrer, antes de comenzar a recorrerlos.
- No es posible modificar el listado original.
¿Cuándo usar un bucle for o una foreach?, en principio la mejor opción
es siempre el bucle foreach, por los motivos establecidos, (sobre todo el de claridad
en el código), salvo en el caso que realmente sea relevante la posición del elemento
en la lista.
No hay comentarios:
Publicar un comentario