Eine while-Schleife wiederholt ihren Rumpf, solange eine Bedingung wahr bleibt. Nimm sie, wenn du im Voraus nicht weißt, wie viele Durchläufe du brauchst: weitermachen, bis ein Kontostand ein Ziel erreicht, eine Queue leer ist oder die Eingabe ausgeht.
Ausgabe:
Year 1: 1070.00
Year 2: 1144.90
Year 3: 1225.04
Year 4: 1310.80
Year 5: 1402.55
Year 6: 1500.73
Goal reached after 6 years
Die Bedingung wird vor jedem Durchlauf geprüft, auch vor dem ersten. Hätte savings das Ziel schon erreicht, liefe der Rumpf nie, und das Programm gäbe „after 0 years“ aus. Die Schleife ist darauf angewiesen, dass der Rumpf etwas ändert, das die Bedingung liest; hier wächst savings jedes Jahr, bis savings < goal false wird.
do while: mindestens einmal ausführen
Eine do while-Schleife verschiebt den Test ans Ende, der Rumpf läuft also immer mindestens einmal:
Ausgabe:
Attempt 1: got 7
Attempt 2: got 4
Attempt 3: got 1
Done after 3 attempts
Der erste Wert von code existiert erst, nachdem der Rumpf einmal gelaufen ist, und genau dann passt do while. Zwei Syntaxdetails erwischen Leute:
- Das Semikolon nach
while (code != 1)ist Pflicht. Wer es weglässt, bekommt einen Kompilierfehler. - Variablen, die in der Bedingung verwendet werden, müssen vor
dodeklariert sein. Eine in den Klammern deklarierte Variable ist nicht mehr gültig, wenn die Bedingung läuft,do { int code = ...; } while (code != 1);kompiliert also nicht.
Dieselbe Schleife mit while geschrieben braucht entweder einen doppelten ersten Aufruf vor der Schleife oder einen Dummy-Startwert, der den ersten Durchlauf erzwingt. do while drückt „versuchen, dann entscheiden, ob noch einmal“ direkt aus.
Eingaben bis zu einem Endwert lesen
Zeilen zu lesen, bis ein Stoppwort kommt oder die Eingabe endet, ist die Lehrbuch-while-Schleife. Console.ReadLine() gibt null zurück, wenn keine Eingabe mehr kommt, prüfe also beides:
Ausgabe:
skipping "abc": not a number
3 amounts, total 49.50
(line = Console.ReadLine()) != null weist die nächste Zeile zu und prüft sie in einem Ausdruck; die Klammern um die Zuweisung sind Pflicht, weil != stärker bindet als =. Die Schleife stoppt bei done, die 99 danach wird also nie gelesen. decimal.TryParse weist abc ab, ohne zu werfen, und continue springt zur nächsten Zeile. Ohne die Prüfung auf null würde am Ende der Eingabe endlos null an TryParse übergeben, weil ReadLine weiterhin null liefert.
Ein do while passt zum Muster „fragen und validieren“, bei dem die Aufforderung mindestens einmal erscheinen muss:
Ausgabe:
Enter your age:
"-4" is not a valid age
Enter your age:
"fifteen" is not a valid age
Enter your age:
Age accepted: 15
Die Aufforderung steht in der Schleife, sie wiederholt sich also nach jeder abgelehnten Antwort, und age ist vor do deklariert, damit der Code nach der Schleife es verwenden kann. Sitzt ein Benutzer an der Tastatur, erscheint jede Antwort nach ihrer Aufforderung in der Konsole; bei umgeleiteter Eingabe wie hier wird nur die eigene Ausgabe des Programms gezeigt.
while (true) mit break
Manchmal liegt der natürliche Ausstiegspunkt mitten im Rumpf, nach etwas Arbeit und vor dem Rest. Schreibe die Schleife als while (true) und verlasse sie mit break:
Ausgabe:
processing: resize photo
processing: send email
stop signal received
1 job(s) left in the queue
Dequeue nimmt den nächsten Job vorn aus der Queue, und die Schleife endet, sobald sie die Stoppmarke sieht, der letzte Job bleibt also in der Queue. while (true) ist kein Code Smell, wenn der Ausstieg klar ist und nahe am Anfang des Rumpfs liegt. Zu einem wird es, wenn mehrere breaks über einen langen Rumpf verstreut sind; dann ist eine benannte bool-Bedingung oder eine Methode mit return leichter nachzuvollziehen. Die Seite zu break und continue behandelt das Verlassen verschachtelter Schleifen.
Schleifen, die nie enden
Eine unbeabsichtigte Endlosschleife hat eine von drei Ursachen.
Der Rumpf ändert die Bedingung nie. Der Zähler wird nie erhöht, oder es wird die falsche Variable erhöht:
int i = 0;
while (i < 5)
{
Console.WriteLine(i); // i++ forgotten: prints 0 forever
}
Ein Semikolon nach der Bedingung. Das Semikolon ist der gesamte Rumpf der Schleife, und der Block darunter läuft nach der Schleife (die nie endet):
while (retries < 3); // warning CS0642: Possible mistaken empty statement
{
retries++;
}
Eine Bedingung, die über ihr Ziel hinausspringt. Mit != zu prüfen, wenn sich die Variable in Schritten bewegt, kann den Stoppwert überspringen. while (x != 10) x += 3; geht 0, 3, 6, 9, 12 und läuft direkt an 10 vorbei (es landet nur zufällig auf 10, nachdem der int Milliarden Schritte später überläuft und umspringt). Prüfe mit < oder > statt !=, wann immer der Schritt nicht 1 ist. Dasselbe gilt für double-Werte, die selten ein exaktes Ziel treffen: while (x != 1.0) x += 0.1; endet nie.
Zwischen while, do while und for wählen
| Situation | Schleife |
|---|---|
| Bekannte Anzahl an Durchläufen oder ein Index | for |
| Jedes Element einer Collection | foreach |
| Wiederholen, solange eine Bedingung gilt, möglicherweise null Mal | while |
| Der Rumpf muss einmal laufen, bevor die Bedingung Sinn ergibt | do while |
| Abbruchtest mitten im Rumpf | while (true) mit break |
Jede for-Schleife lässt sich als while-Schleife schreiben und umgekehrt; die Wahl entscheidet, welche Form die Logik der Schleife dort platziert, wo ein Leser sie erwartet. Wenn Zähler, Test und Schritt alle existieren, hält for sie in einer Zeile. Wenn die Schleife von einem Zustand gesteuert wird, der sich im Rumpf ändert, sagt while genau das.
Häufig gestellte Fragen
Was ist der Unterschied zwischen while und do while in C#?
Eine while-Schleife prüft ihre Bedingung vor jedem Durchlauf, ihr Rumpf kann also null Mal laufen. Eine Schleife do { } while (condition); prüft nach jedem Durchlauf, ihr Rumpf läuft also immer mindestens einmal. Nimm do while, wenn der erste Durchlauf den Wert erzeugt, den die Bedingung prüft, etwa eine Eingabe lesen und dann validieren.
Wie lautet die Syntax einer do-while-Schleife in C#?
do { body } while (condition);. Beachte das Semikolon nach der schließenden Klammer: Es ist Pflicht, und wer es weglässt, bekommt einen Kompilierfehler. Die Bedingung kann Variablen verwenden, die im Rumpf zugewiesen werden, aber sie müssen vor dem do deklariert sein, weil die Klammern des Rumpfs ein eigener Gültigkeitsbereich sind.
Wie schreibe ich while (true) in C#?
while (true) { ... } läuft endlos, bis etwas darin die Schleife mit break, return oder einer Exception verlässt. Das ist die natürliche Form, wenn der Abbruchtest mitten in den Rumpf gehört, etwa eine Zeile lesen und aufhören, wenn sie leer ist.
Wie lese ich in C# Eingaben, bis der Benutzer ein Wort tippt oder die Eingabe endet?
Lass die Schleife über Console.ReadLine() laufen, das am Ende der Eingabe null zurückgibt: string line; while ((line = Console.ReadLine()) != null && line != "done") { ... }. Die Zuweisung in der Bedingung liest die nächste Zeile und prüft sie in einem Schritt.
Warum endet meine C#-while-Schleife nie?
Meist ändert der Rumpf nie, was die Bedingung prüft (ein vergessenes i++), oder direkt nach der Bedingung steht ein Semikolon: while (count < 10); ist eine Schleife mit leerem Rumpf, die endlos läuft. Beim zweiten Fall warnt der Compiler mit CS0642, Possible mistaken empty statement.