Lesson 4 · ~14 min · ← Lesson 3
Loops: for, while, do-while, foreach
Four loops, one mental model: repeat a body while a condition holds. The differences are about where the counting lives and what you're iterating over.
for: when you know how many times
Three clauses in the header — start, keep-going test, step:
for (int i = 1; i <= 5; i++) // start i at 1; repeat while i <= 5; i++ after each pass
{
Console.Write(i * 2 + " ");
}
Console.WriteLine();
The loop variable i is born and dies inside the for — trying to use it after the loop is error CS0103.
The accumulator pattern
The single most useful loop shape: a variable declared before the loop, updated every pass:
int sum = 0; // accumulator starts at 0 — always
int count = 0;
for (int i = 1; i <= 5; i++)
{
sum += i; // fold each value in
count++;
}
Console.WriteLine($"sum: {sum}, count: {count}");
while: when you DON'T know how many times
// double a number until it passes 10 — how many passes? we don't know yet
int n = 1;
while (n <= 10)
{
Console.WriteLine(n);
n = n * 2; // without this line: infinite loop (see below)
}
Rule: something inside the body must move the condition toward false. The engine here has a step-watchdog that stops runaway loops instead of freezing your tab — in Visual Studio, an infinite loop just… runs.
do-while: check AFTER, run at least once
Classic for input validation — ask first, then decide whether to ask again:
string[] attempts = { "abc", "-5", "42" };
int pos = 0;
int value;
do
{
int.TryParse(attempts[pos], out value); // try to parse the next attempt
pos++;
} while (value <= 0); // loop again if we didn't get a positive number
Console.WriteLine("accepted: " + value);
A plain while checks before the first pass — if the condition is false immediately, the body never runs. do-while guarantees one pass. That difference is exactly why Count the Digits solves its n = 0 edge case with a do-while.
foreach: over a collection, no counting at all
int[] scores = { 72, 95, 88 };
foreach (int s in scores) // "for each element, call it s"
{
Console.WriteLine("score: " + s);
}
Console.Write("letters in Ada: ");
foreach (char c in "Ada") // strings are sequences of chars
{
Console.Write(c + " ");
}
Console.WriteLine();
break and continue: steering from inside
int[] scores = { 72, 95, 88 };
// break: leave the loop entirely (first match)
for (int i = 0; i < scores.Length; i++)
{
if (scores[i] > 90)
{
Console.WriteLine($"found {scores[i]} at index {i}");
break;
}
}
// continue: skip the rest of THIS pass only
for (int i = 1; i <= 5; i++)
{
if (i % 2 == 0) continue; // skip evens
Console.Write(i + " ");
}
Nested loops: the multiplication table corner
for (int row = 1; row <= 3; row++)
{
for (int col = 1; col <= 3; col++)
{
Console.Write(row * col + " ");
}
Console.WriteLine(); // newline after each row — note WHERE it sits
}
The inner loop runs completely for every single step of the outer one: 3 × 3 = 9 prints. The classic beginner bug is putting the WriteLine() inside the inner loop (every number on its own line) or outside both (everything on one line) — run it and move it around until the shape makes sense.
Which loop when?
| Loop | Reach for it when… | Signature move |
|---|---|---|
for | You know how many passes (or the range) | Counting: for (int i = 0; i < n; i++) |
while | Repeat until a condition changes; maybe zero times | Sentinel: "until input is valid" |
do-while | Same, but at least once | Menu / retry prompts |
foreach | You want the elements, not the indexes | Summing, printing a collection |
Practice this now
- Sum 1..100 with a
for, then verify with Gauss's formulan * (n + 1) / 2. - Print the 3×3 table with only the diagonal cells (row == col).
- Get graded: Sum from 1 to N then Count the Digits — both are pure loop craft.