A while loop repeats its body as long as a condition stays true. Use it when you do not know in advance how many iterations you need: keep going until a balance reaches a target, a queue is empty, or the input runs out.
Output:
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
The condition is checked before every iteration, including the first. If savings already met the goal, the body would never run and the program would print "after 0 years". The loop depends on the body changing something the condition reads; here savings grows each year until savings < goal becomes false.
do while: Run at Least Once
A do while loop moves the test to the end, so the body always runs at least once:
Output:
Attempt 1: got 7
Attempt 2: got 4
Attempt 3: got 1
Done after 3 attempts
The first value of code only exists after the body has run once, which is exactly when a do while fits. Two syntax details catch people:
- The semicolon after
while (code != 1)is required. Leaving it out is a compile error. - Variables used in the condition must be declared before
do. A variable declared inside the braces is out of scope by the time the condition runs, sodo { int code = ...; } while (code != 1);does not compile.
The same loop written with while needs either a duplicated first call before the loop or a dummy starting value that forces the first pass. do while expresses "try, then decide whether to try again" directly.
Reading Input Until a Sentinel
Reading lines until a stop word, or until input ends, is the textbook while loop. Console.ReadLine() returns null when there is no more input, so test for both:
Output:
skipping "abc": not a number
3 amounts, total 49.50
(line = Console.ReadLine()) != null assigns the next line and tests it in one expression; the parentheses around the assignment are required because != binds tighter than =. The loop stops at done, so the 99 after it is never read. decimal.TryParse rejects abc without throwing, and continue skips to the next line. Without the null check, reaching the end of input would pass null to TryParse forever, since ReadLine keeps returning null.
A do while suits the prompt-and-validate pattern, where the prompt must appear at least once:
Output:
Enter your age:
"-4" is not a valid age
Enter your age:
"fifteen" is not a valid age
Enter your age:
Age accepted: 15
The prompt is inside the loop, so it repeats after every rejected answer, and age is declared before do so the code after the loop can use it. With a user at the keyboard, each answer appears on the console after its prompt; with redirected input, as here, only the program's own output is shown.
while (true) with break
Sometimes the natural exit point is in the middle of the body, after some work and before the rest. Write the loop as while (true) and leave with break:
Output:
processing: resize photo
processing: send email
stop signal received
1 job(s) left in the queue
Dequeue takes the next job off the front of the queue, and the loop leaves as soon as it sees the stop marker, so the last job stays queued. while (true) is not a code smell when the exit is clear and close to the top of the body. It becomes one when there are several breaks scattered through a long body; then a named bool condition or a method with return is easier to follow. The break and continue page covers leaving nested loops.
Loops That Never End
An unintended infinite loop has one of three causes.
The body never changes the condition. The counter is never incremented, or the wrong variable is:
int i = 0;
while (i < 5)
{
Console.WriteLine(i); // i++ forgotten: prints 0 forever
}
A semicolon after the condition. The semicolon is the loop's entire body, and the block below it runs after the loop (which never finishes):
while (retries < 3); // warning CS0642: Possible mistaken empty statement
{
retries++;
}
A condition that skips past its target. Testing != when the variable moves in steps can jump over the stopping value. while (x != 10) x += 3; goes 0, 3, 6, 9, 12 and runs straight past 10 (it only lands on 10 by accident, after the int overflows and wraps around billions of steps later). Test with < or > instead of != whenever the step is not 1. The same applies to double values, which rarely hit an exact target: while (x != 1.0) x += 0.1; never ends.
Choosing Between while, do while and for
| Situation | Loop |
|---|---|
| Known number of iterations, or an index | for |
| Every element of a collection | foreach |
| Repeat while a condition holds, possibly zero times | while |
| Body must run once before the condition makes sense | do while |
| Exit test in the middle of the body | while (true) with break |
Any for loop can be rewritten as a while loop and vice versa; the choice is about which one puts the loop's logic where a reader expects it. When the counter, the test and the step all exist, for keeps them on one line. When the loop is driven by state that changes inside the body, while says so.
Frequently Asked Questions
What is the difference between while and do while in C#?
A while loop checks its condition before each iteration, so its body can run zero times. A do { } while (condition); loop checks after each iteration, so its body always runs at least once. Use do while when the first pass produces the value the condition tests, such as reading input and then validating it.
What is the syntax of a do while loop in C#?
do { body } while (condition);. Note the semicolon after the closing parenthesis: it is required, and leaving it out is a compile error. The condition can use variables assigned in the body, but they must be declared before the do, because the body's braces are a separate scope.
How do I write while (true) in C#?
while (true) { ... } loops forever until something inside it leaves with break, return or an exception. It is the natural shape when the exit test belongs in the middle of the body, such as reading a line and stopping when it is empty.
How do I read input until the user types a word or input ends in C#?
Loop on Console.ReadLine(), which returns null at the end of input: string line; while ((line = Console.ReadLine()) != null && line != "done") { ... }. The assignment inside the condition reads the next line and tests it in one step.
Why does my C# while loop never end?
Usually the body never changes what the condition tests (a forgotten i++), or there is a semicolon right after the condition: while (count < 10); is a loop with an empty body that spins forever. The compiler warns about the second case with CS0642, Possible mistaken empty statement.