Sintácticamente veo que giran indefinidamente hasta que se alcanza una declaración de interrupción, pero ¿se compilan para la misma cosa? ¿Es ligeramente más rápido porque no tiene una condición para verificar? Aparte de la legibilidad del código, ¿hay alguna diferencia?Diferencia entre for (;;) y while (true) en C#?
Respuesta
Dada esta entrada:
private static void ForLoop()
{
int n = 0;
for (; ;)
{
Console.WriteLine(n++);
}
}
private static void WhileLoop()
{
int n = 0;
while (true)
{
Console.WriteLine(n++);
}
}
... se obtiene este resultado:
.method private hidebysig static void ForLoop() cil managed
{
// Code size 14 (0xe)
.maxstack 3
.locals init ([0] int32 n)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: br.s IL_0002
} // end of method Program::ForLoop
.method private hidebysig static void WhileLoop() cil managed
{
// Code size 14 (0xe)
.maxstack 3
.locals init ([0] int32 n)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
IL_000c: br.s IL_0002
} // end of method Program::WhileLoop
notablemente similares, diría (idéntico, incluso).
A menos que me falta algo, son * idénticos *, fuera de los comentarios y nombres de los identificadores. –
@ T.E.D. sí, son idénticos. –
Hmm, hay una diferencia en la línea 5 ... oh, espera, no, eso es un punto en mi monitor;) –
No he examinado el código de salida, pero no debería haber diferencia alguna. Cualquier compilador decente hará la optimización de bucle lo suficientemente simple para ver que la condición es una expresión constante, y por lo tanto no necesita comprobar cada iteración.
Si uno es más rápido que el otro, los escritores de compilador de C# necesitan algo 'splained a ellos ...
En los compiladores modernos, absolutamente nada.
Históricamente, sin embargo, for(;;)
se implementó como un salto único, mientras que while(true)
también tenía una verificación de verdadero.
Prefiero while(true)
, ya que deja más claro lo que estoy haciendo.
+1 absolutamente. 'while (true)' es mucho más claro que 'for (;;)'. ¿Qué estoy esperando, de todos modos? –
Estoy totalmente de acuerdo en que debes elegir el que creas que es más claro, aunque podría estar en desacuerdo sobre cuál es ... –
¿por qué no 'loop: ... goto loop'? –
Recopilan lo mismo. Puede escribir una aplicación de prueba que implemente ambos métodos y luego use ILDASM para confirmar que IL es idéntico.
O simplemente puede ver la respuesta de Fredrik y ahorrarse el problema. :) – DarLom
Un ensamblaje de depuración se cumple hasta while (verdadero). Usa el reflector y puedes ver los resultados.
static void Main(string[] args)
{
ExecuteWhile();
ExecuteFor();
}
private static void ExecuteFor()
{
for (; ;)
{
Console.WriteLine("for");
string val = Console.ReadLine();
if (string.IsNullOrEmpty(val))
{
Console.WriteLine("Exit for.");
break;
}
}
}
private static void ExecuteWhile()
{
while (true)
{
Console.WriteLine("while");
string val = Console.ReadLine();
if (string.IsNullOrEmpty(val))
{
Console.WriteLine("Exit while.");
break;
}
}
}
Inspección del método ExecuteFor
en Reflector.
private static void ExecuteFor()
{
while (true)
{
Console.WriteLine("for");
if (string.IsNullOrEmpty(Console.ReadLine()))
{
Console.WriteLine("Exit for.");
return;
}
}
}
una versión optimizada del mismo código produce resultados diferentes para ExecuteFor
private static void ExecuteFor()
{
do
{
Console.WriteLine("for");
}
while (!string.IsNullOrEmpty(Console.ReadLine()));
Console.WriteLine("Exit for.");
}
Por nivel de detalle aquí es el ExecuteWhile
optimizado ...
private static void ExecuteWhile()
{
do
{
Console.WriteLine("while");
}
while (!string.IsNullOrEmpty(Console.ReadLine()));
Console.WriteLine("Exit while.");
}
¿Realmente se compila hasta 'while (true)', o el reflector lo descompila de esa manera? : p –
Si observa el IL creado a partir de los mismos ensamblajes, lee de esa manera. –
Como han mencionado otros, con cualquier compilador moderno, no debería hacer absolutamente ninguna diferencia.
Hice una breve prueba en mi computadora, sincronizando un par de operaciones usando una u otra, y siempre tomaron casi el mismo tiempo. Por supuesto, debido a otros procesos en ejecución, estas pruebas no son 100% precisas, pero si hay una diferencia en la velocidad (no debería haber), entonces es una microscópica.
Si pudiera, sugiero que vea una pregunta algo diferente. Si usa cualquiera de estos con la frecuencia suficiente para importarle, probablemente esté estructurando su código de manera deficiente. Si bien hay cosas como los sistemas integrados que realmente funcionan para siempre, los bucles en la mayoría del código normal no lo hacen. Escribir un bucle que reclama para que funcione para siempre significa que ha ocultado la condición de salida para el bucle en algún lugar dentro, con algún otro flujo de control (p., if (whatever) break;
) como real salir del bucle.
Eso puede y debe evitarse. Si bien hay situaciones en las que las declaraciones break
tienen sentido, generalmente deben ser para manejar situaciones inusuales, no para escribir un ciclo que dice una cosa pero hace otra (es decir, dice "ejecutar para siempre", pero realmente "ejecutar hasta que se cumpla la condición")
No puedo estar de acuerdo con esto. –
Yo tampoco. Cuando estaba aprendiendo a programar por primera vez en PL/I (no sé si incluso tenía una declaración de "interrupción") el patrón era "lectura de línea de archivo; mientras que no es el marcador final, haz el ciclo, que termina leyendo la siguiente línea ". Eso parece una violación de "no te repitas". Sugeriría que leer la línea una vez, al comienzo del ciclo, y salir si es un marcador final, es un mejor estilo. – supercat
@supercat: Estoy de acuerdo, pero no justifica nada. Debería estar haciendo 'while (file.getline())', not 'for (;;) if (! File.getline()) break;' –
- 1. ¿Cuál es la diferencia entre while (true) y loop?
- 2. while (true) frente a (;;)
- 3. PC Lint while (TRUE) vs for (;;)
- 4. Diferencia entre "while" y "until" en Bash
- 5. Diferencia entre el bucle "while" y el bucle "do while"
- 6. Diferencia entre AutoPostBack = True y AutoPostBack = ¿Falso?
- 7. Directriz: while vs for
- 8. Python - Threading y un while True Loop
- 9. ¿Cuál es el punto de emitir una advertencia de compilación para "while (true)" y no emitir una para "for (;;)"?
- 10. ¿Cuál es la diferencia entre: while y: when in clojure?
- 11. ¿Cuál es la diferencia entre Boolean.TRUE y true en Java?
- 12. Diferencia entre C: y C:/
- 13. python -c y `while`
- 14. Diferencia entre i ++ y ++ i en un bucle for
- 15. ¿Qué significa while (true) {mean en PHP?
- 16. Cuándo usar "while" o "for" en Python
- 17. Eficiencia de while (true) ServerSocket Escucha
- 18. iPhone: diferencia entre nil vs Nil y verdadero vs TRUE
- 19. ¿Cuál es la diferencia entre FileStream.Flush() y FileStream.Flush (True)?
- 20. diferencia entre sizeof y strlen en c
- 21. For-loop vs while loop en R
- 22. Diferencia entre read() y fgets() en C
- 23. C# diferencia entre == y equals()
- 24. para y while loop en C#
- 25. Rendimiento C++, para versus while
- 26. ¿Diferencia entre == y caso?
- 27. ¿Cuál es la diferencia entre for..in y for each..in en javascript?
- 28. Diferencia entre foreach y for bucles sobre una clase IEnumerable en C#
- 29. ¿Diferencia entre sombreado y anulación en C#?
- 30. Diferencia entre byte y char en C
Ver http://stackoverflow.com/questions/2288856/when-implementing-an-infinite-loop-is-there-a-difference-in-using-while1-vs-fo –
Esta es una buena pregunta. Me parece interesante ver que el compilador optimiza el código en un bucle do while en el código de ejemplo con el que probé esto. –
'for (;;)' es A) escrito por antiguos codificadores de C, y B) cuatro caracteres más cortos :) – hobbs