C# While and Do-While Loops: Repeat Work and Stop Clearly
A loop needs more than a true condition: its state must progress toward a clear stopping rule. Learn to trace each iteration, choose a before-or-after check, and repeat input safely with a fixed attempt limit.
What you will understand
- Trace initial state, condition, body and update for a while loop.
- Explain why a while body can execute zero times.
- Distinguish do-while’s mandatory first iteration.
- Keep an accumulator outside the repeated body.
- Recognize stale conditions and off-by-one updates.
- Read fresh input and distinguish a sentinel, a blank line and end of input.
- Define a bounded retry budget and when an attempt is consumed.
- Prove that every retry path progresses or stops.
A while loop checks before every iteration
A loop repeats a block while its condition allows another iteration. An iteration is one execution of the body. In a while loop, the condition is checked before the first iteration and again after each completed body. A false check transfers execution to the statements after the loop.
Read four parts together: the initial state, the condition, the work and the update. The condition does not automatically change the state. If nothing makes it false and no path exits, the loop can continue indefinitely. A correct loop needs a reason its work can eventually finish.
You need variables, Boolean conditions and if/else from earlier lessons. Each example is a complete Program.cs. Predict the values that enter the body before running it. The deliberately stale-condition example is bounded for inspection; this lesson does not ask you to run an unbounded loop.
Program.cs · Check, run, update, then check again
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Step 1
Step 2
Step 3
After loop: 4
The condition is checked before each iteration. The body prints the current step and increments it. When step becomes 4, the next check is false and execution continues after the loop. The update does not happen automatically: it is an ordinary statement in the body.
Program.cs · A while body may run zero times
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Nothing left to process.
The first condition is already false, so the body never runs. This behavior is useful when no work exists. A while loop is not a promise that its body executes at least once, and an action inside it cannot initialize a value needed before the loop starts.
Explain what moves closer to the stopping boundary
For a countdown starting at three, remaining > 0 permits three iterations if the body subtracts one each time. The state moves through three, two, one and finally zero. At zero the condition fails. This small nonnegative count gives a simple argument that the loop stops.
An update in the wrong direction can invalidate that reasoning. So can resetting the counter inside the body, or saving a Boolean once and mistakenly expecting it to track later state changes. Prefer a condition reading the current state when that states the rule directly.
For larger or arbitrary inputs, consider the numeric representation too. Overflow can break an otherwise plausible progress argument. These counter examples use small fixed integers so the focus stays on flow; a bounded retry additionally provides an explicit maximum amount of work.
Program.cs · Move the state toward the stopping condition
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Remaining: 3
Remaining: 2
Remaining: 1
Complete.
remaining is a nonnegative small count in this exercise. Subtracting one each time eventually makes remaining > 0 false. Increasing it instead would move away from the intended stop. Describe how a changing value approaches the boundary before trusting a loop.
Program.cs · A stored Boolean does not update with the counter
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Remaining: 2
Remaining: 1
Remaining: 0
Remaining: -1
Stored hasWork: True
hasWork was calculated once and never reassigned. It stays true even after remaining reaches zero. The separate four-iteration observation limit intentionally makes this demonstration finite; it is not the repair. Use the current state in the real condition, or deliberately recompute the stored flag.
Trace the condition value and work value separately
Off-by-one errors often come from considering a stop condition without its starting value. Zero through three contains four values. One through three contains three. Write down the actual values admitted by the condition instead of guessing from the final number alone.
Update placement also matters. Checking label <= 3 and then incrementing before printing lets a value of four appear. That program still prints three lines, so a line-count check alone misses the bug. Verify both how many iterations run and what each iteration does.
Use a short trace on paper: state before check, condition result, body output, state after update. Include the final false check. The guided repair later asks you to restore the intended labels without hardcoding three separate output statements.
Program.cs · Starting at zero changes an inclusive boundary
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Label 0
Label 1
Label 2
Label 3
Zero through three includes four values. An inclusive final boundary must be considered together with the starting value. If the requirement is three human-readable labels numbered one through three, start at one. If the requirement is three zero-based positions, use position < 3.
State outside the body persists across iterations
A loop can accumulate a result while advancing through inputs. Initialize a total once before the body, add the current value during each iteration, and then advance to the next value. The sum example prints its intermediate totals so you can follow each addition.
Declaring or resetting the accumulator inside the body would start a new total each time. Keep the scope and lifetime aligned with the work: a value needed after the loop must be declared in a scope that includes that later use.
An accumulator is not automatically an average or a count of accepted values. Name what you add and when you add it. In input loops, decide explicitly whether blank, invalid or sentinel entries count toward a total or an attempt budget.
Program.cs · Keep the accumulator outside the loop
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
After 1: 1
After 2: 3
After 3: 6
After 4: 10
Total: 10
total retains the running sum across iterations because it is initialized before the loop. Each iteration adds the current number before incrementing it. Moving total = 0 into the body would reset the sum repeatedly. These small inputs fit int; a general summation also needs range considerations.
A do-while always enters its body once
A do-while checks its condition after the body rather than before. Even if the initial condition would be false, the first body still runs. This is useful when the required action must happen before you can decide whether it should repeat, such as showing a prompt and reading its answer.
The syntax ends with while (condition); after the closing brace. That semicolon belongs to do-while syntax. It differs from an accidental semicolon immediately after a standalone while condition, which would create an empty loop body.
Do not choose do-while just to avoid an initial state assignment. If no work exists, processing one item can be wrong. The zero-remaining example intentionally exposes that mismatch. Choose the loop form from whether zero executions or at least one execution is appropriate.
Program.cs · A do-while checks after its first body
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Body sees: 0
After loop: -1
The body executes once before the condition is checked, even when the initial remaining value is zero. The negative result deliberately shows why this form is inappropriate for blindly processing an empty work count. The semicolon after the final while condition is required in do-while syntax.
Program.cs · Use do-while when one read should always happen
Predict the result, edit Program.cs, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Type done to finish.
Type done to finish.
Prompt finished.
The prompt and read happen before the condition. A different command repeats the prompt, while done or end of input stops it. command is declared outside the body so the trailing condition can read it; every path through the body assigns it first.
Read fresh input and stop when the stream ends
An input-driven loop needs a fresh read for each next answer. Reusing the same line cannot discover a sentinel or a corrected quantity. In the sentinel example, one read establishes the starting state and the bottom read advances it before the next condition.
The website runner receives all standard-input lines before execution and then closes the stream. Expand Standard input, edit the prefilled answers and select Run. The output does not echo supplied input, and typing into the output pane cannot provide later answers. A local terminal can instead wait for each entered line.
ReadLine returns null at end of input. Treat that as a stopping signal when no more answers can arrive. A blank supplied line is an empty string, not null. The sentinel example counts blank notes; the retry example treats blank quantities as failed attempts. Those are deliberate field policies.
Program.cs · Read a fresh line before repeating
Predict the result, edit Program.cs, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Enter notes; type done to stop.
Note 1: Review variables
Note 2: Practice loops
Notes read: 2
The first read supplies the initial state, and the read at the bottom advances it. The sentinel done is not counted as a note; end of input also stops the loop. Text after the sentinel is not processed. A blank line counts as a note under this example’s explicit policy.
Bound retries and define what consumes an attempt
A retry loop needs a success condition, a limit and a missing-input policy. The bounded example stops when a quantity is accepted, three supplied attempts are used, or the input stream ends. A valid number outside the allowed interval still consumes an attempt and receives feedback.
The attempt counter is incremented after confirming that a line was supplied. Therefore invalid text and blank lines count, but an absent line does not. The prompt may appear before the program discovers that input has ended; the summary reports the lines actually consumed.
break exits the loop, so the final summary still executes. return would end the whole top-level run. This is a first, small use of break for end of input; a later lesson covers loop-control choices in depth. Do not rely on an execution timeout as the loop’s intended stopping rule.
Program.cs · Bound retries and stop on end of input
Predict the result, edit Program.cs, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Quantity attempt 1 (1 to 6)?
Enter a whole number from 1 to 6.
Quantity attempt 2 (1 to 6)?
Enter a whole number from 1 to 6.
Quantity attempt 3 (1 to 6)?
Accepted: 4
Attempts used: 3
The attempt limit and success flag are both stop conditions. Each supplied line, including a blank or invalid one, consumes an attempt; an absent line does not. The null guard breaks only the loop, so the final summary still runs. This is a bounded validation exercise, not a real authentication retry policy.
Guided repair: update at the right moment
The program should print labels one through three, but it prints two through four. Explain the difference between the value checked and the value printed, then repair the update order.
Program.cs · A misplaced update skips the first label
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Label 2
Label 3
Label 4
The condition allows label = 3 to enter, then the increment changes it to 4 before printing. This produces the right number of lines with the wrong values. Trace the condition value separately from the value used by the work statement.
Repair checkpoints
- Keep one loop rather than replacing it with three hardcoded messages.
- Print the current label before advancing to the next.
- Expect exactly Label 1, Label 2 and Label 3.
- Change the upper bound to 1: print one label, not Label 2.
- With an upper bound of 0 and the same initial label, print nothing.
Reveal the repair and explanation
Program.cs · Print the current label before advancing
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Label 1
Label 2
Label 3
The update now prepares the next iteration rather than changing the current label before use. Once label becomes four, the following check rejects another iteration. This order matches the stated numbering requirement; changing the output text alone would not repair the state flow.
Independent lab: a bounded quantity retry
Read a quantity from one to six, allowing at most three supplied lines. Stop immediately on acceptance or end of input, and report how many attempts were actually consumed.
Acceptance checklist
- Prefill 0 followed by 4 on separate input lines for the reference run.
- Use a while condition that combines the remaining attempt budget and absence of success.
- Read a fresh line inside each iteration and break on null without consuming an attempt.
- Count each supplied line once, including invalid or blank lines.
- Require both TryParse success and an inclusive quantity range of 1 to 6.
- After success, do not read or process another answer.
- Always print attempts used; print No quantity accepted only when none was accepted.
Program.cs · Quantity retry starter
Predict the result, edit Program.cs, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Attempt 1: quantity 1 to 6?
Accepted: 0
Attempt 2: quantity 1 to 6?
Accepted: 4
Attempt 3: quantity 1 to 6?
Retry exercise finished.
The starter counts a missing line as an attempt, accepts zero despite the rule and keeps prompting after valid input. Its finite attempt limit prevents an endless run, but the state and acceptance policy still need repair.
Show hints
- Use a bool success flag that is initialized before the loop.
- Check null before incrementing the attempt count.
- Every rejected supplied line must advance the attempt counter; every accepted line must stop the next iteration.
Reveal the reference solution
Program.cs · Quantity retry reference solution
Predict the result, edit Program.cs, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Attempt 1: quantity 1 to 6?
Use a whole number from 1 to 6.
Attempt 2: quantity 1 to 6?
Accepted: 4
Attempts used: 2
Every path either consumes a supplied line, stops at end of input, or ends repetition after acceptance or the attempt limit. Parsing and domain checks must both succeed. The final result distinguishes an accepted quantity from exhaustion or input ending. This validates one quantity and prints it without creating a request.
Changed-input checks
- A first-line 1 or 6 succeeds using one attempt.
- two, 0, 7 exhaust all three attempts without acceptance.
- An empty stream uses zero attempts and reports input ended.
- A blank line then 4 uses two attempts and succeeds.
- two followed by end of input uses one attempt, then stops.
- Three invalid lines followed by 4 must not process the fourth line.
Recap: check, work, update and stop
Choose whether the check belongs before or after the body, keep updates on every continuing path, and define what happens at input exhaustion.
while (condition)- Check before each body; zero iterations are possible.
do { ... } while (condition);- Check after the body; the first iteration always runs.
state update- Advance the counter or input so the next check has fresh information.
accumulator- Initialize once, update across iterations and use after repetition.
sentinel- A documented input value meaning stop; decide whether it counts as data.
ReadLine() is null- End of the supplied input stream, distinct from a blank line.
attempts < limit && !accepted- Stop on either a full attempt budget or successful acceptance.
break- Leave the loop and continue with its following summary.
Frequently asked questions
Does while run at least once?
No. Its condition is checked before entering the body. A do-while runs its body once before its first condition check.
Does the loop counter update automatically?
Not in a while or do-while. An update such as counter++ is an ordinary statement you must place on the appropriate path.
Why does my loop still use an old Boolean value?
A bool calculated before the loop is a stored snapshot. It does not automatically recompute when the counter or other source data changes.
Why stop when ReadLine returns null?
The supplied stream has ended. Repeating a read cannot manufacture a new line. A retry loop should stop or apply a deliberate end-of-input policy.
Is a blank line an attempt?
That is your application rule. In this lab every supplied line counts, including blank lines, but an absent line does not.
Should I test an endless loop to understand it?
Trace the missing progress first. The stale-condition demonstration has a separate inspection bound so it finishes. A timeout is a runtime limit, not the intended correctness condition of a loop.
Can you trace the next iteration?
Trace progress, update placement, input consumption and stopping paths. Read each explanation after checking your answers.
Next step and references
A correct loop has a clear entry condition, useful work and a state change that supports its stopping rule. Test zero work, one iteration, final boundaries, acceptance and input exhaustion. Do not rely on an execution timeout for correctness.
Next is C# For and Foreach Loops. You will repeat counted work and visit values while keeping positions and collection boundaries clear.
Official references
Original SovranCode explanations, examples and exercises. Technical details were checked against these references.
Last updated: .