Welches ist die richtige C # -Unendelschleife für (;;) oder while (true)? [geschlossen]


97

Zurück in meinen C / C ++ Tagen, Codierung einer "Endlosschleife" als

while (true)

fühlte sich natürlicher an und schien mir offensichtlicher als im Gegensatz zu

for (;;)

Eine Begegnung mit PC-Flusen in den späten 1980er Jahren und anschließende Best-Practice-Diskussionen haben mich von dieser Gewohnheit befreit. Ich habe seitdem die Schleifen mit der forSteueranweisung codiert . Heute, zum ersten Mal seit langer Zeit und vielleicht als erster Bedarf an einer Endlosschleife als C # -Entwickler, stehe ich vor der gleichen Situation. Ist einer von ihnen richtig und der andere nicht?


5
Vier identische Antworten in weniger als zwei Minuten. Nicht schlecht.
Jon B

5
Sie könnten das ganze religiöse Argument vermeiden, indem Sie Ihre Endlosschleife abrollen. Sollte nicht lange dauern ...
Stephen Darlington

7
Nur aus Neugier: Warum ist für (;;) in C / C ++ besser?
Vilx

6
@Vilx, wie ich mich erinnere, haben alte Compiler mit for (;;) effizienteren Code geschrieben als while (1). Ich bin sicher, dass jeder anständige moderne Compiler ziemlich identischen Code ausgeben wird.
Stephen Darlington

4
Aufbauend auf den Kommentaren von Stephen und Serhio: 1. while(true)erfordert eine Bedingung. for(;;)ist daher eine bessere Darstellung für Endlosschleifen, die sich bedingungslos wiederholen. 2. Alte, nicht optimierende Compiler haben möglicherweise tatsächlich die (true)Schleife ausgewertet . 3. C ist eine minimalistische Sprache aus der Zeit der Teletypen, 300 Baud-Terminals und 1-Zeichen-Variablennamen. In einer Umgebung, in der jeder Tastendruck zählt, for(;;)ist er viel kürzer als while(true).
Richard Dingwall

Antworten:


124
while(true)
{

}

Ist immer das, was ich verwendet habe und was andere für eine Schleife verwendet haben, die manuell unterbrochen werden muss.


@RSolberg - es war ein Fehler zwischen den beiden ähnlichen Antworten, die innerhalb von Sekunden angeboten wurden. Adams nachfolgender Kommentar führte dazu, dass ich eine Antwort akzeptierte, die eher auf der Verwendung als auf der Konvention beruhte.
Bob Kaufman

1
während und für können beide manuell gebrochen werden
Allen Rice

2
Leider beantwortet diese Antwort die Frage nicht. Die richtige Antwort lautet "beide sind richtig".
David R Tribble

2
@ Loadmaster: Das hängt von Ihrer Definition von "richtig" ab (oder vielmehr davon, nach welcher Art von "Korrektheit" Sie suchen).
Adam Robinson

314

Der C # -Compiler transformiert beide

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

und

while (true)
{
    // ...
}

in

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

Die CIL ist für beide gleich. Die meisten Menschen finden while(true)es leichter zu lesen und zu verstehen.for(;;)ist eher kryptisch.

Quelle:

Ich habe ein bisschen mehr mit .NET Reflector rumgespielt und beide Schleifen mit dem "Code optimieren" in Visual Studio kompiliert.

Beide Schleifen werden kompiliert (mit .NET Reflector):

Label_0000:
    goto Label_0000;

Raptoren sollten bald angreifen.


7
yup, nur doppelt überprüft, es ist alles der gleiche IL-Code, dies sollte die akzeptierte Antwort sein IMO :)
Allen Rice

63
+1 für die xkcd Referenz
Ikke

4
Um pedantisch zu sein, transformiert der Compiler nicht eine Anweisungsform in die andere. Vielmehr wird für beide Anweisungen identischer Code generiert. Dieser Code ist gotoübrigens identisch mit einer Aussage, was keine Überraschung ist.
David R Tribble

1
und dann wird das goto in eine jmp-Anweisung übersetzt.
Marco M.

25
so offensichtlich goto LOOPist die richtige C # Endlosschleife :)
Dustin Getz

61

Ich denke, dass dies leichter zu lesen ist und definitiv der Standard für die Verwendung in C # ist:

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

19
@voyager: 1 ist kein Ersatz für 'true' in C #.
Adam Robinson

17
Beachten Sie, dass während (1) ungültig ist C #: Konstante 1 nicht in bool konvertiert werden kann
Vinko Vrsalovic

4
while(1)ist in C # nicht gültig, da 1es nicht a ist bool.
Pavel Minaev

47

Keuchen, benutzen:

while (!false)
{

}

ODER wie jsight hervorhob , möchten Sie vielleicht doppelt sicher sein:

while (!false && true)
{
}

Bevor die Leute mich anschreien, ist es alles der gleiche CIL-Code, den ich überprüft habe :)


Beste Antwort aller Zeiten.
Larry

38

Um ein paar alte Witze aufzuwärmen:

  1. Verwenden Sie nicht " for (;;) {}" - es bringt die Aussage zum Weinen.
  2. Es sei denn natürlich, Sie " #define EVER ;;".

24
Oder #define ever (;;)was ich für lesbarer halte. for ever {}
Chris Lutz

1
Ich hätte nicht gedacht, dass du jemals ein #define (;;) in C # machen könntest, aber der Witz ist lustig :)
Allen Rice

1
Ah. Ich programmiere C unter OS X. Ich wusste nicht, dass der C # -Vorprozessor so kastriert ist. Ich bin mir nicht mal sicher, wie ich angefangen habe, diese Frage zu lesen. Ich habe C # als ignoriertes Tag ...
Chris Lutz

Der C # -Vorprozessor ist nicht wirklich ein Präprozessor, zumindest nicht in Bezug auf das, was C, C ++, PL / 1 und sogar Makro-Assembler bieten. Sie können Codeblöcke nur aktivieren oder deaktivieren, indem Sie Präprozessorsymbole definieren / aufheben.
David R Tribble

6
Oder noch besser : #define forever while(true);)
Roberto Bonvallet

26

Wenn Sie auf die alte Schule gehen möchten, wird goto in C # weiterhin unterstützt:

STARTOVER:  
    //Do something
    goto STARTOVER;

Für eine wirklich Endlosschleife ist dies der Befehl go-to. =)



6
Ich habe dies von einer negativen Bewertung auf Null zurückgestuft, aber nur wegen seines Humorwerts. Hey, alle Schleifen werden sowieso in JMP-Assembler-Opcodes kompiliert, oder?
David R Tribble

@ Loadmaster: Danke, ich habe es nur als eine andere Option rausgeworfen und es nicht unbedingt gebilligt.
JohnFx

2
@serhio: Umso mehr vermeiden Sie Sprachkonstrukte, weil Sie irgendwo etwas lesen. Kein Sprachelement an sich ist schlecht, es kann nur schlecht verwendet werden.
JohnFx

2
@serhio: Ich habe Greuel gegen die Natur mit fast jedem möglichen Schlüsselwort gesehen. Es ist nicht das Sprachelement, es ist der Programmierer. Wie in meinem vorherigen Kommentar erwähnt, habe ich es auf keinen Fall befürwortet. Ich habe es nur der Vollständigkeit halber und mit einem Hauch von Humor aufgenommen.
JohnFx


10

In solchen Situationen, in denen ich eine echte Endlosschleife brauchte, habe ich immer verwendet

while(true) {...}

Es scheint die Absicht besser auszudrücken als eine leere Aussage.


10

Persönlich habe ich es immer vorgezogen, for(;;)gerade weil es keine Bedingung hat (im Gegensatz zu while (true)der, die immer wahr ist). Dies ist jedoch wirklich ein sehr kleiner Stilpunkt, über den ich meiner Meinung nach nicht streiten sollte. Ich habe noch keine C # -Stilrichtlinie gesehen, die einen der beiden Ansätze vorgeschrieben oder verboten hat.


In .NET nicht wert, wenn der Compiler Ihre (schlecht lesbare) für eine Weile ohne Bedingung mit Bedingung transformiert .
Serhio

3
@serhio: Bitte erklären Sie, was Sie unter "Compiler-Transformationen ... in a while" verstehen . Für den Programmierer wandelt der Compiler High-Level-Code in IL um. Es gibt keine while(oder for) Schleifen in IL, nur Labels und Gotos.
Pavel Minaev

1
siehe die Antwort von Pierre-Alain Vigeant.
Serhio

3
Seine Antwort kann besser umformuliert werden, indem einfach "der Compiler für beide identische IL generiert" (Sie wissen nicht wirklich, ob und wann etwas auf AST-Ebene transformiert wird, und es ist auf jeden Fall ein Implementierungsdetail). In jedem Fall erklärt dies nicht, warum es sich in .NET nicht lohnt. Das gleiche gilt auch für C ++, Java ...
Pavel Minaev

6

Ich persönlich bevorzuge die for (;;)Redewendung (aus C / C ++ - Sicht). Ich stimme zwar zu, dass das while (true)in gewissem Sinne besser lesbar ist (und es ist das, was ich vor langer Zeit verwendet habe, selbst in C / C ++), aber ich habe mich der Verwendung der forRedewendung zugewandt, weil:

  • Es steht heraus

Ich denke, die Tatsache, dass eine Schleife nicht endet (auf normale Weise), ist es wert, "herausgerufen" zu werden, und ich denke, dass das for (;;)ein bisschen mehr tut.


Schließlich werden wir damit etwas länger warten, bis die Programme kompiliert sind (Transformation kompilieren von for => while)
serhio

3
@serhio: Nicht wirklich. Es transformiert es nicht von fornach while. Für beide for (;;){}und while (true){}generiert es neuen while(true){}Code. Siehe diese Antwort .
Wchargin

6

Das ursprüngliche K & R- Buch für C, aus dem C # seine Herkunft ableiten kann, wird empfohlen

for (;;) ...

für Endlosschleifen. Es ist eindeutig, leicht zu lesen und hat eine lange und edle Geschichte.

Nachtrag (Februar 2017)

Wenn Sie der Meinung sind, dass dieses Schleifenformular (oder ein anderes Formular) zu kryptisch ist, können Sie natürlich immer nur einen Kommentar hinzufügen .

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

Oder:

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

1
ja, aber das ist für C, nicht für C #.
Serhio

1
Es funktioniert in C #. Und die C # -Sprache wurde (indirekt) von C. abgeleitet
David R Tribble

4
8 Jahre später haben Sie beschlossen, Ihre Antwort zu aktualisieren. Nizza
Metoniem

4

Es sollte while(true)nicht sein while(1), while(1)ist also in C # falsch, ja;)


2

Alternativ könnte man sagen, dass eine Endlosschleife normalerweise sowieso eine schlechte Praxis ist, da sie eine Exit-Bedingung benötigt, es sei denn, die App läuft wirklich für immer. Wenn dies jedoch für eine Marschflugkörper gilt, akzeptiere ich, dass eine explizite Ausstiegsbedingung möglicherweise nicht erforderlich ist.

Obwohl ich diesen mag:

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

2
-1: Nicht jeder wird verstehen, dass Ihre "Endlosschleife" den Code liest. Vielleicht könnte jemand denken, dass dies ein Fehler ist, und versuchen, ihn zu "beheben" ...
serhio

In C # f < 16777217fist immer false... also wird dies nie wiederholt.
NetMage

2

Ich bevorzuge etwas mehr "gebildeten" Code. Ich mache so etwas in der Praxis viel eher:

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

    shouldContinue = CheckSomething();
}

1
Pfui. Eigentlich ist das eine do ... while()verschleierte Schleife. Ich habe nur ein paar Sekunden gebraucht, um das zu sehen. Wenn Sie eine do ... while()Schleife geschrieben hätten, wäre dies sofort klar gewesen. -1
sbi

Warum Zeit und Ressourcen verschwenden, um eine Variable zu deklarieren, wenn Sie while (true) verwenden können? Es macht meiner Meinung nach keinen Sinn
waqasahmed

Ich finde es besser lesbar, insbesondere wenn Sie ein bestimmtes aussagekräftiges Flag anhängen können, z. B. "while (! This.cancelled)", um anzuzeigen, dass die Stornierung die einzige Möglichkeit ist, die Schleife zu stoppen, "while (! ProcessExited)", um die Schleife anzuzeigen sollte ausgeführt werden, bis ein externer Prozess verschwindet usw. Es gibt viele Dinge, die möglicherweise "Ressourcen verschwenden", die im Namen der einfachen Wartbarkeit oder Lesbarkeit absolut richtig sind. "while (true)" ist gar nicht so schlecht, aber meiner Erfahrung nach gibt es normalerweise einen besseren Weg.
Bobbymcr

1
+1. In den meisten Fällen ist eine echte Endlosschleife nicht das, was tatsächlich passiert, und Sie haben eine Bedingung, unter der Sie anhalten möchten (z. B. wenn der Drucker in Flammen steht).
Lie Ryan

1
… In welchem ​​Fall sollten Sie verwenden break.
Ry-


1

Wenn Sie Code-Golf spielen, würde ich vorschlagen for(;;). Darüber hinaus while(true)hat die gleiche Bedeutung und scheint intuitiver. Auf jeden Fall werden die meisten Programmierer wahrscheinlich beide Variationen verstehen, also spielt es keine Rolle. Verwenden Sie das, was am bequemsten ist.


2
Wenn Sie Golf spielen, ist C # sowieso die falsche Sprache.
SingleNegationElimination

1

Der einzige Grund, den ich sagen würde, for(;;)sind die CodeDom-Einschränkungen (während Schleifen nicht mit CodeDom deklariert werden können und for-Schleifen als allgemeinere Form als Iterationsschleife angesehen werden).

Dies ist ein ziemlich loser Grund, dies anders zu wählen als die Tatsache, dass die for Schleifenimplementierung sowohl für normalen Code als auch für von CodeDom generierten Code verwendet werden kann. Das heißt, es kann mehr Standard sein.

Als Hinweis können Sie Code-Snippets verwenden, um eine whileSchleife zu erstellen , aber die gesamte Schleife müsste ein Snippet sein ...


1

Beide haben die gleiche Funktion, aber die Leute bevorzugen im Allgemeinen while(true). Es fühlt sich leicht zu lesen und zu verstehen ...


0

Jeder Ausdruck, der immer true zurückgibt, sollte für die while-Schleife in Ordnung sein.

Beispiel:

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

Warum sollten Sie sich jemals die Mühe machen, einen Vergleich wie 1 = 1 durchzuführen, wenn true genauso gut funktioniert? Die Verwendung eines berechneten Ausdrucks ist ungefähr so ​​albern wie die Definition einer Konstante wie NUMBER_OF_ARMS = 598-3596;
JohnFx

Es ist ein Beispiel für die Antwort vor dem Code :)
George

0

In Bezug auf die Lesbarkeit des Codes while(true) in jeder Sprache ist dies meiner Meinung nach sinnvoller. In Bezug darauf, wie der Computer es sieht, sollte es in der heutigen Gesellschaft wirklich keinen Unterschied zwischen sehr effizienten Compilern und Interpreten geben.

Wenn es Leistungsunterschiede gibt, wird die Übersetzung in MSIL sicher nicht mehr optimiert. Sie könnten das überprüfen, wenn Sie wirklich wollten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.