Qual è il ciclo infinito C # corretto, for (;;) o while (true)? [chiuso]


97

Ai miei tempi C / C ++, codificando un "ciclo infinito" come

while (true)

sembrava più naturale e mi sembrava più ovvio rispetto a

for (;;)

Un incontro con PC-lint alla fine degli anni '80 e le successive discussioni sulle migliori pratiche mi hanno rotto questa abitudine. Da allora ho codificato i cicli usando l' foristruzione di controllo. Oggi, per la prima volta da molto tempo, e forse il mio primo bisogno di un ciclo infinito come sviluppatore C #, sto affrontando la stessa situazione. Uno di loro è corretto e l'altro no?


5
Quattro risposte identiche in meno di due minuti. Non male.
Jon B,

5
Potresti evitare l'intera discussione religiosa svolgendo il tuo ciclo infinito. Non dovrebbe volerci molto ...
Stephen Darlington,

7
Solo per curiosità: perché è per (;;) meglio in C / C ++?
Vilx

6
@Vilx per come lo ricordo, i vecchi compilatori scrivevano codice più efficiente con for (;;) rispetto a while (1). Sono sicuro che qualsiasi compilatore moderno decente produrrà codice praticamente identico.
Stephen Darlington,

4
Basandosi sui commenti di Stephen e Serhio: 1. while(true)richiede una condizione. for(;;)è quindi una rappresentazione migliore per cicli infiniti che si ripetono incondizionatamente. 2. I vecchi compilatori che non ottimizzano l'ottimizzazione potrebbero aver effettivamente valutato il (true)durante il ciclo. 3. C è un linguaggio minimalista dai tempi dei telescriventi, dei terminali a 300 baud e dei nomi di variabili da 1 carattere. In un ambiente in cui ogni battuta di tasto conta, for(;;)è un po 'più breve di while(true).
Richard Dingwall

Risposte:


124
while(true)
{

}

È sempre quello che ho usato e quello che ho visto usare gli altri per un loop che deve essere interrotto manualmente.


@RSolberg - è stato un litigio tra le due risposte simili offerte a pochi secondi l'una dall'altra. Il commento successivo di Adam mi ha portato ad accettare una risposta basata sull'uso piuttosto che sulle convenzioni.
Bob Kaufman,

1
mentre e per possono essere entrambi interrotti manualmente
Allen Rice

2
Sfortunatamente, questa risposta non risponde alla domanda. La risposta corretta è "entrambi sono corretti".
David R Tribble

2
@Loadmaster: Dipende dalla tua definizione di "corretto" (o piuttosto che tipo di "correttezza" stai cercando).
Adam Robinson

314

Il compilatore C # trasformerà entrambi

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

e

while (true)
{
    // ...
}

in

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

Il CIL per entrambi è lo stesso. La maggior parte delle persone trova while(true)più facile leggere e capire. for(;;)è piuttosto criptico.

Fonte:

Ho lavorato un po 'di più con .NET Reflector e ho compilato entrambi i cicli con "Ottimizza codice" in Visual Studio.

Entrambi i cicli vengono compilati in (con .NET Reflector):

Label_0000:
    goto Label_0000;

I rapaci dovrebbero attaccare presto.


7
sì, appena ricontrollato, è sempre lo stesso codice IL, questa dovrebbe essere la risposta accettata IMO :)
Allen Rice

63
+1 per il riferimento xkcd
Ikke

4
Per essere pedante, il compilatore non trasforma una forma di dichiarazione nell'altra; piuttosto, genera un codice identico per entrambe le istruzioni. Quel codice è identico a gotoun'istruzione, btw, che non è una sorpresa.
David R Tribble,

1
e poi il goto viene tradotto in un'istruzione jmp ..
Marco M.

25
quindi ovviamente goto LOOPè il ciclo infinito C # corretto :)
Dustin Getz

61

Penso che questo possa essere più facile da leggere ed è sicuramente lo standard per l'uso in C #:

while(true)
{
   //Do My Loop Stuff
}

19
@voyager: 1 non è un sostituto di "true" in C #.
Adam Robinson,

17
Nota che mentre (1) non è valido C #: la costante 1 non può essere convertita in bool
Vinko Vrsalovic

4
while(1)non è valido in C #, poiché 1non è un file bool.
Pavel Minaev,

47

Gasp, usa:

while (!false)
{

}

O come ha sottolineato jsight , potresti essere doppiamente sicuro:

while (!false && true)
{
}

Prima che la gente mi sgridi, è tutto lo stesso codice CIL, ho controllato :)


La migliore risposta in assoluto.
Larry

38

Per riproporre un paio di vecchie barzellette:

  1. Non usare " for (;;) {}" - fa piangere l'affermazione.
  2. A meno che, ovviamente, tu " #define EVER ;;".

25
O #define ever (;;)che penso sia più leggibile. for ever {}
Chris Lutz,

1
Non pensavo si potesse fare un #define mai (;;) in C #, però, la battuta è divertente :)
Allen Rice

1
Ah. Programma C su OS X. Non sapevo che il preprocessore C # fosse così castrato. Non sono nemmeno sicuro di come ho iniziato a leggere questa domanda, ho C # come tag ignorato ...
Chris Lutz

Il preprocessore C # non è realmente un preprocessore, almeno non in termini di ciò che forniscono C, C ++, PL / 1 e persino gli assemblatori di macro. Permette solo di abilitare o disabilitare blocchi di codice definendo / non definendo i simboli del preprocessore.
David R Tribble,

6
O ancora meglio #define forever while(true)
:;

26

Se vuoi passare alla vecchia scuola, goto è ancora supportato in C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Per un ciclo veramente infinito, questo è il comando da fare. =)



6
Ho votato al rialzo da una valutazione negativa a zero, ma solo per il suo valore umoristico. Ehi, tutti i loop vengono comunque compilati nei codici operativi dell'assembler JMP, giusto?
David R Tribble,

@Loadmaster: Grazie, lo stavo solo lanciando come un'altra opzione, non necessariamente approvandolo.
JohnFx,

2
@serhio: Ancora di più è evitare costrutti linguistici fuori mano perché leggi qualcosa da qualche parte. Nessun elemento del linguaggio di per sé è cattivo, può essere usato solo in modi sbagliati.
JohnFx

2
@ serhio: ho visto abomini contro natura usare quasi tutte le parole chiave possibili. Non è l'elemento del linguaggio, è il programmatore. In ogni caso, come notato nel mio commento precedente, non l'ho approvato. Lo stavo includendo solo per completezza e un pizzico di umorismo.
JohnFx


10

In quelle situazioni in cui avevo bisogno di un vero loop infinito, l'ho sempre usato

while(true) {...}

Sembra esprimere l'intento meglio di un'affermazione vuota.


10

Personalmente, ho sempre preferito for(;;)proprio perché ha alcuna condizione (a differenza while (true)che ha un sempre vero). Tuttavia, questo è davvero un punto di stile molto minore, su cui non credo valga la pena discutere in entrambi i casi. Devo ancora vedere una linea guida in stile C # che imponga o proibisca entrambi gli approcci.


non vale la pena in .NET, quando il compilatore trasforma il tuo (mal leggibile) per senza condizione in un po ' con condizione.
serhio

3
@ serhio: per favore spiega cosa intendi per "il compilatore trasforma ... in un while". Per quanto riguarda il programmatore, il compilatore trasforma il codice di alto livello in IL. Non ci sono while(o for) loop in IL, solo label e gotos.
Pavel Minaev

1
vedere la risposta di Pierre-Alain Vigeant.
serhio

3
La sua risposta può essere riformulata meglio semplicemente come "il compilatore genera IL identico per entrambi" (non sai davvero se e quando trasforma qualcosa a livello AST, ed è comunque un dettaglio di implementazione). In ogni caso, questo non spiega perché "non ne vale la pena in .NET". Lo stesso vale anche per C ++, Java ...
Pavel Minaev

6

Personalmente preferisco l' for (;;)idioma (proveniente da un punto di vista C / C ++). Sebbene sia d'accordo sul fatto che while (true)sia più leggibile in un certo senso (ed è quello che ho usato molto tempo fa anche in C / C ++), mi sono rivolto a usare l' foridioma perché:

  • si distingue

Penso che il fatto che un ciclo non termini (in modo normale) valga la pena di essere "richiamato", e penso che lo for (;;)faccia un po 'di più.


infine, usando quello aspetteremo ancora un po 'che i programmi si compilino (compilare la trasformazione da for => while)
serhio

3
@ serhio: Non proprio. Non lo trasforma da fora while. Per entrambi for (;;){}e while (true){}, genera nuovo while(true){}codice. Vedi questa risposta .
carica il

6

Consigliato il libro originale di K&R per C, da cui C # può risalire ai suoi antenati

for (;;) ...

per cicli infiniti. È inequivocabile, facile da leggere e ha una lunga e nobile storia alle spalle.

Addendum (febbraio 2017)

Ovviamente, se pensi che questo modulo (o qualsiasi altro modulo) sia troppo criptico, puoi sempre aggiungere un commento .

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

O:

for (;;)    // Loop forever
    ...

1
sì, ma questo è per C, non per C #.
serhio

1
Funziona in C #. E il linguaggio C # è stato derivato (indirettamente) da C.
David R Tribble

4
8 anni dopo hai deciso di aggiornare la tua risposta. Nizza
Metoniem

4

Dovrebbe essere while(true)non while(1), quindi while(1)non è corretto in C #, sì;)


2

In alternativa, si potrebbe dire che avere un ciclo infinito normalmente è comunque una cattiva pratica, poiché richiede una condizione di uscita a meno che l'app non funzioni per sempre. Tuttavia, se questo è per un missile da crociera, accetterò che una condizione di uscita esplicita potrebbe non essere richiesta.

Anche se mi piace questo:

for (float f = 16777216f; f < 16777217f; f++) { } 

2
-1: non tutti capiranno il tuo "loop infinito" leggendo il codice, forse qualcuno potrebbe pensare che questo sia un bug e provare a "aggiustarlo" ...
serhio

In C # f < 16777217fè sempre false... quindi questo non si ripete mai.
NetMage

2

Preferisco un codice leggermente più "alfabetizzato". Sono molto più propensi a fare qualcosa di simile in pratica:

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

    shouldContinue = CheckSomething();
}

1
Uffa. In realtà, è un do ... while()loop mascherato. Mi ci sono voluti solo pochi secondi per vederlo. Se avessi scritto un do ... while()ciclo, sarebbe stato chiaro immediatamente. -1
sbi

perché sprecare tempo e risorse dichiarando una variabile quando puoi usare while (vero)? Non ha senso secondo me
waqasahmed il

Lo trovo più leggibile, soprattutto se puoi allegare un flag significativo specifico, ad esempio "while (! This.canceled)" per indicare che la cancellazione è l'unico modo per interrompere il ciclo, "while (! ProcessExited)" per indicare il ciclo dovrebbe funzionare finché un processo esterno non scompare, ecc. Ci sono molte cose che probabilmente "sprecano risorse" che sono assolutamente la cosa giusta da fare in nome della facilità di manutenzione o leggibilità. "while (true)" non è poi così male, ma nella mia esperienza di solito c'è un modo migliore.
bobbymcr

1
+1. Nella maggior parte dei casi, un vero ciclo infinito non è ciò che accade realmente, e hai qualche condizione in cui vorresti fermarti (ad esempio quando la stampante è in fiamme).
Lie Ryan,

1
... in questo caso dovresti usare break.
Ry-


1

Se stai giocando a golf in codice, ti suggerirei for(;;). Oltre a ciò, while(true)ha lo stesso significato e sembra più intuitivo. In ogni caso, la maggior parte dei programmatori probabilmente capirà entrambe le varianti, quindi non ha molta importanza. Usa ciò che è più comodo.


2
se stai giocando a golf, C # è comunque la lingua sbagliata.
SingleNegationElimination

1

L'unico motivo per cui direi for(;;) è dovuto alle limitazioni di CodeDom (mentre i cicli non possono essere dichiarati utilizzando CodeDom e i cicli for sono visti come la forma più generale come un ciclo di iterazione).

Questo è un motivo piuttosto approssimativo per scegliere questo diverso dal fatto che il file for implementazione ciclo può essere utilizzata sia per il codice normale che per il codice generato da CodeDom. Cioè, può essere più standard.

Come nota, puoi usare frammenti di codice per creare un whileciclo, ma l'intero ciclo dovrebbe essere uno snippet ...


1

Entrambi hanno la stessa funzione, ma le persone generalmente preferiscono while(true). È facile da leggere e da capire ...


0

Qualsiasi espressione che restituisce sempre true dovrebbe essere OK per il ciclo while.

Esempio:

1==1 //Just an example for the text stated before 
true

Perché mai dovresti costringerlo a fare un confronto come 1 = 1 quando true funziona altrettanto bene? Usare un'espressione calcolata sembra sciocco quanto definire una costante come NUMBER_OF_ARMS = 598-3596;
JohnFx,

È un esempio per la risposta dichiarata prima del codice :)
George

0

In termini di leggibilità del codice while(true) in qualsiasi lingua ritengo abbia più senso. In termini di come il computer lo vede, non dovrebbe esserci alcuna differenza nella società odierna di compilatori e interpreti molto efficienti.

Se c'è qualche differenza di prestazioni da avere, sono sicuro che la traduzione in MSIL verrà ottimizzata. Potresti controllarlo se lo volessi davvero.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.