¿Cuál es el ciclo infinito de C # correcto, para (;;) o while (verdadero)? [cerrado]

97

En mis días de C / C ++, codificaba un "bucle infinito" como

while (true)

se sentía más natural y me parecía más obvio en lugar de

for (;;)

Un encuentro con PC-lint a fines de la década de 1980 y las posteriores discusiones sobre las mejores prácticas me rompieron este hábito. Desde entonces he codificado los bucles usando la fordeclaración de control. Hoy, por primera vez en mucho tiempo, y quizás mi primera necesidad de un bucle infinito como desarrollador de C #, me enfrento a la misma situación. ¿Es correcto uno de ellos y el otro no?

Bob Kaufman
fuente
5
Cuatro respuestas idénticas en menos de dos minutos. No está mal.
Jon B
5
Podrías evitar todo el argumento religioso desenrollando tu bucle infinito. No debería tomar mucho tiempo ...
Stephen Darlington
7
Solo por curiosidad: ¿por qué es (;;) mejor en C / C ++?
Vilx-
6
@Vilx, como lo recuerdo, los compiladores antiguos solían escribir código más eficiente con for (;;) que while (1). Estoy seguro de que cualquier compilador moderno decente generará un código prácticamente idéntico.
Stephen Darlington
4
Basándose en los comentarios de Stephen y Serhio: 1. while(true)requiere una condición. for(;;)por lo tanto, es una mejor representación para bucles infinitos que se repiten incondicionalmente. 2. Es posible que los compiladores antiguos no optimizados hayan evaluado realmente el (true)bucle. 3. C es un lenguaje minimalista de la época de los teletipos, terminales de 300 baudios y nombres de variables de 1 carácter. En un entorno donde cada pulsación de tecla cuenta, for(;;)es bastante más corto que while(true).
Richard Dingwall

Respuestas:

124
while(true)
{

}

Siempre es lo que he usado y lo que he visto que otros usan para un bucle que debe romperse manualmente.

Adam Robinson
fuente
@RSolberg: fue un cambio entre las dos respuestas similares ofrecidas en segundos. El comentario de seguimiento de Adam me llevó a aceptar una respuesta basada en el uso en lugar de la convención.
Bob Kaufman
1
while y for se pueden romper manualmente
Allen Rice
2
Desafortunadamente, esta respuesta no responde a la pregunta. La respuesta correcta es "ambos son correctos".
David R Tribble
2
@Loadmaster: Eso depende de su definición de "correcto" (o, más bien, qué tipo de "corrección" está buscando).
Adam Robinson
314

El compilador de C # transformará ambos

for(;;)
{
    // ...
}

y

while (true)
{
    // ...
}

dentro

{
    :label
    // ...
    goto label;
}

El CIL para ambos es el mismo. La mayoría de las personas encuentran while(true)que es más fácil de leer y comprender.for(;;)es bastante críptico.

Fuente:

Me metí un poco más con .NET Reflector , y compilé ambos bucles con "Optimizar código" en Visual Studio.

Ambos bucles se compilan en (con .NET Reflector):

Label_0000:
    goto Label_0000;

Las rapaces deberían atacar pronto.

Pierre-Alain Vigeant
fuente
7
sí, solo verifiqué dos veces, es todo el mismo código IL, esta debería ser la respuesta aceptada IMO :)
Allen Rice
63
+1 para la referencia xkcd
Ikke
4
Para ser pedante, el compilador no transforma una forma de declaración en otra; más bien, genera código idéntico para ambas declaraciones. Ese código es idéntico a una gotodeclaración, por cierto, lo cual no es ninguna sorpresa.
David R Tribble
1
y luego el goto se traduce a una instrucción jmp ..
Marco M.
25
entonces obviamente goto LOOPes el ciclo infinito C # correcto :)
Dustin Getz
61

Creo que esto puede ser más fácil de leer y definitivamente es el estándar para usar en C #:

while(true)
{
   //Do My Loop Stuff
}
RSolberg
fuente
19
@voyager: 1 no es un sustituto de 'verdadero' en C #.
Adam Robinson
17
Tenga en cuenta que mientras (1) no es válido C #: la constante 1 no se puede convertir a bool
Vinko Vrsalovic
4
while(1)no es válido en C #, ya 1que no es un bool.
Pavel Minaev
47

Jadeo, uso:

while (!false)
{

}

O como señaló jsight , es posible que desee estar doblemente seguro:

while (!false && true)
{
}

Antes de que la gente me grite, es todo el mismo código CIL, lo comprobé :)

Arroz Allen
fuente
La mejor respuesta de todas.
Larry
38

Para repetir un par de viejos chistes:

  1. No use " for (;;) {}" - hace llorar la declaración.
  2. A menos que, por supuesto, usted " #define EVER ;;".
Ben Blank
fuente
25
O #define ever (;;)que creo que es más legible. for ever {}
Chris Lutz
1
No pensé que pudieras hacer un #define nunca (;;) en C #, sin embargo, la broma es divertida :)
Allen Rice
1
¡Ah! Programando C en OS X. No sabía que el preprocesador de C # estaba tan castrado. Ni siquiera estoy seguro de cómo comencé a leer esta pregunta, tengo C # como una etiqueta ignorada ...
Chris Lutz
El preprocesador de C # no es realmente un preprocesador, al menos no en términos de lo que proporcionan C, C ++, PL / 1 e incluso los ensambladores de macros. Solo le permite habilitar o deshabilitar bloques de código definiendo / indefiniendo símbolos de preprocesador.
David R Tribble
6
O incluso mejor #define forever while(true):;)
Roberto Bonvallet
26

Si desea ir a la vieja escuela, goto todavía es compatible con C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Para un bucle verdaderamente infinito, este es el comando de acceso. =)

JohnFx
fuente
9
xkcd.com/292
Callum Rogers
6
Elegí esto de una calificación negativa a cero, pero solo por su valor de humor. Oye, todos los bucles se compilan en códigos de operación de ensamblador JMP de todos modos, ¿verdad?
David R Tribble
@Loadmaster: Gracias, solo lo estaba lanzando como otra opción, no necesariamente apoyándolo.
JohnFx
2
@serhio: Aún más es evitar las construcciones del lenguaje porque lees algo en alguna parte. Ningún elemento del lenguaje por sí solo es malo, solo se puede usar de manera incorrecta.
JohnFx
2
@serhio: He visto abominaciones contra la naturaleza usando casi todas las palabras clave posibles. No es el elemento del lenguaje, es el programador. En cualquier caso, como se señaló en mi comentario anterior, no lo respaldaba. Solo lo estaba incluyendo para completar y un cosquilleo de humor.
JohnFx
21

Creo que while (true)es un poco más legible.

Marplesoft
fuente
10

En aquellas situaciones en las que necesitaba un verdadero bucle infinito, siempre he usado

while(true) {...}

Parece expresar mejor la intención que una declaración vacía.

Michael Petrotta
fuente
10

Personalmente, siempre he preferido for(;;)precisamente porque tiene ninguna condición (a diferencia de while (true)que tiene un siempre-verdadero). Sin embargo, este es realmente un punto de estilo muy menor, sobre el que no creo que valga la pena discutir de ninguna manera. Todavía no he visto una guía de estilo de C # que obligue o prohíba cualquiera de los enfoques.

Pavel Minaev
fuente
no vale la pena hacer en NET, al compilador transforma su (mala legible) para sin condición en un tiempo con condiciones.
serhio
3
@serhio: por favor explique lo que quiere decir con "transformaciones de compilador ... en un while". En lo que respecta al programador, el compilador transforma el código de alto nivel en IL. No hay bucles while(o for) en IL, solo etiquetas y gotos.
Pavel Minaev
1
vea la respuesta de Pierre-Alain Vigeant.
serhio
3
Su respuesta puede reformularse mejor como simplemente "el compilador genera IL idéntico para ambos" (no se sabe realmente si transforma algo en el nivel AST y cuándo, y es un detalle de implementación en cualquier caso). En cualquier caso, esto no explica por qué "no vale la pena en .NET". Lo mismo ocurre con C ++, Java ...
Pavel Minaev
6

Personalmente prefiero el for (;;)idioma (desde el punto de vista de C / C ++). Si bien estoy de acuerdo en que while (true)es más legible en cierto sentido (y es lo que usé hace mucho tiempo incluso en C / C ++), he recurrido a usar el foridioma porque:

  • se destaca

Creo que el hecho de que un bucle no termine (de manera normal) vale la pena "llamarlo", y creo que lo for (;;)hace un poco más.

Michael Burr
fuente
finalmente, usando eso, esperaremos un poco más que los programas compilen (compile la transformación de for => while)
serhio
3
@serhio: Realmente no. No lo transforma de fora while. Para ambos for (;;){}y while (true){}, genera while(true){}código nuevo . Vea esta respuesta .
wchargin
6

Se recomienda el libro original de K&R para C, del cual C # puede rastrear su ascendencia

for (;;) ...

para bucles infinitos. Es inequívoco, fácil de leer y tiene una larga y noble historia detrás.

Anexo (febrero de 2017)

Por supuesto, si cree que esta forma de bucle (o cualquier otra forma) es demasiado críptica, siempre puede agregar un comentario .

// Infinite loop
for (;;)
    ...

O:

for (;;)    // Loop forever
    ...
David R Tribble
fuente
1
sí, pero esto es para C, no para C #.
serhio
1
Funciona en C #. Y el lenguaje C # se derivó (indirectamente) de C.
David R Tribble
4
8 años después, decidió actualizar su respuesta. Niza
Metoniem
4

No debería ser while(true)así while(1), por lo que while(1)es incorrecto en C #, sí;)

JRL
fuente
2

Alternativamente, se podría decir que tener un bucle infinito es normalmente una mala práctica de todos modos, ya que necesita una condición de salida a menos que la aplicación realmente se ejecute para siempre. Sin embargo, si esto es para un misil de crucero, aceptaré que no se requiera una condición de salida explícita.

Aunque me gusta este:

for (float f = 16777216f; f < 16777217f; f++) { } 
Chris Chilvers
fuente
2
-1: no todos entenderán su "bucle infinito" leyendo el código, tal vez alguien podría pensar que esto es un error y tratar de "arreglarlo" ...
serhio
En C # f < 16777217fes siempre false... así que esto nunca se repite.
NetMage
2

Prefiero un código un poco más "alfabetizado". Es mucho más probable que haga algo como esto en la práctica:

bool shouldContinue = true;
while (shouldContinue)
{
    // ...

    shouldContinue = CheckSomething();
}
bobbymcr
fuente
1
Ugh. En realidad, eso es un do ... while()bucle disfrazado. Solo me tomó unos segundos ver eso. Si hubiera escrito un do ... while()bucle, habría quedado claro de inmediato. -1
sbi
¿Por qué perder tiempo y recursos declarando una variable cuando puedes usar while (verdadero)? No tiene sentido en mi opinión
waqasahmed
Lo encuentro más legible, especialmente si puede adjuntar una bandera significativa específica, por ejemplo, "while (! This.canceled)" para indicar que la cancelación es la única forma de detener el bucle, "while (! ProcessExited)" para indicar el bucle debería ejecutarse hasta que un proceso externo desaparezca, etc. Hay muchas cosas que posiblemente "desperdician recursos" que son absolutamente lo correcto en nombre de la facilidad de mantenimiento o legibilidad. "mientras (cierto)" no es tan malo, pero en mi experiencia, generalmente hay una mejor manera.
bobbymcr
1
+1. En la mayoría de los casos, un verdadero bucle infinito no es lo que realmente sucede, y tiene alguna condición en la que desearía detenerse (por ejemplo, cuando la impresora está en llamas).
Lie Ryan
1
… En cuyo caso debería utilizar break.
Ry-
2

Incluso yo también digo que el de abajo es mejor :)

while(true)
{

}
anishMarokey
fuente
1

Si estás jugando al golf con códigos, te sugiero for(;;). Más allá de eso, while(true)tiene el mismo significado y parece más intuitivo. En cualquier caso, es probable que la mayoría de los programadores comprendan ambas variaciones, por lo que en realidad no importa. Usa lo que te resulte más cómodo.

sobeliano
fuente
2
si está jugando al golf, C # es el idioma incorrecto de todos modos.
SingleNegationElimination
1

La única razón por la que diría for(;;) es debido a las limitaciones de CodeDom (mientras que los bucles no se pueden declarar usando CodeDom y los bucles for se consideran la forma más general como un bucle de iteración).

Esta es una razón bastante imprecisa para elegir esto además del hecho de que for implementación bucle se puede usar tanto para código normal como para código generado por CodeDom. Es decir, puede ser más estándar.

Como nota, puede usar fragmentos de código para crear un whilebucle, pero el bucle completo debería ser un fragmento ...

Mark Synowiec
fuente
1

Ambos tienen la misma función, pero la gente generalmente lo prefiere while(true). Se siente fácil de leer y comprender ...

abhinav
fuente
0

Cualquier expresión que siempre devuelva verdadero debería estar bien para el ciclo while.

Ejemplo:

1==1 //Just an example for the text stated before 
true
Jorge
fuente
¿Por qué te molestarías en obligarlo a hacer una comparación como 1 = 1 cuando verdadero funciona igual de bien? Usar una expresión calculada se siente tan tonto como definir una constante como NUMBER_OF_ARMS = 598-3596;
JohnFx
Es un ejemplo de la respuesta indicada antes del código :)
George
0

En términos de legibilidad del código while(true)en cualquier idioma, creo que tiene más sentido. En términos de cómo lo ve la computadora, realmente no debería haber ninguna diferencia en la sociedad actual de compiladores e intérpretes muy eficientes.

Si hay alguna diferencia de rendimiento, estoy seguro de que la traducción a MSIL se optimizará. Podrías comprobarlo si realmente quisieras.

Chris
fuente