for, while and do-while

for counts, while tests before the body, and do-while tests after it, so a do-while always runs its body at least once.

Syntaxfor (initializer; condition; iterator) { ... } | while (condition) { ... } | do { ... } while (condition);

A loop repeats a block of code. C# has three loops that differ mainly in where the test sits, and choosing between them is a question of what the loop knows before it starts.

for, when the counting is known

for holds three parts in its header, separated by semicolons. The initializer runs once before the first pass. The condition is checked before every pass and must be a bool. The iterator runs after each pass, usually to step a counter. A variable declared in the initializer exists only inside the loop.

while, when only the condition is known

while keeps a single test at the top and checks it before each pass, so it can run zero times. A for is the same loop written compactly: the example below shows both, and the only difference is that for keeps the counter next to the test instead of above the loop.

do-while, when the body must run once

do puts the body first and the test after it, so the body always runs at least once, even if the condition was never true. Use it when you cannot judge the condition until the work has been done once. Note the semicolon after the closing while (...); it is part of the statement.

Leaving early

break ends the loop immediately. continue skips the rest of the body and starts the next pass, and in a for the iterator still runs, so a continue there does not skip the step. Every loop needs something inside it that eventually makes the condition false, or it never ends.

Example

Example · csharp
// A for loop: start, keep-going test, step after each pass.
for (int i = 1; i <= 3; i++)
{
    Console.WriteLine($"for {i}");
}

// The same loop as a while. Identical work; the counter just moves
// out of the header and the step moves into the body.
int j = 1;
while (j <= 3)
{
    Console.WriteLine($"while {j}");
    j++;
}

// A do loop tests after the body, so the body always runs once.
int attempts = 0;
do
{
    attempts++;
}
while (attempts < 1);   // false the first time it is reached

Console.WriteLine($"attempts: {attempts}");

// Output:
// for 1
// for 2
// for 3
// while 1
// while 2
// while 3
// attempts: 1

When to use it

  • Sum the numbers from 1 to 100 with a counting loop.
  • Keep halving a value until it drops below a threshold.
  • Scan a string character by character looking for the first separator.
  • Retry an operation up to three times, where the first attempt always happens.

More examples

break and continue

A search loop is the clearest use of break: once the answer is known, the remaining passes are wasted work. continue is the opposite move, used to skip the uninteresting items early so the rest of the body is not wrapped in an if. Both read best when the loop body stays short.

Example · csharp
string word = "soundscode";
int found = -1;

// Stop as soon as there is an answer. -1 means "not found".
for (int i = 0; i < word.Length; i++)
{
    if (word[i] == 'd')
    {
        found = i;
        break;
    }
}

Console.WriteLine($"first d at {found}");

int count = 0;
for (int i = 0; i < word.Length; i++)
{
    if (word[i] != 'o')
    {
        continue;   // skip the rest of the body for this character
    }

    count++;
}

Console.WriteLine($"letter o appears {count} times");

// Output:
// first d at 4
// letter o appears 2 times

A loop inside a loop

Nested loops are how you work over something with two dimensions: rows and columns, days and hours, or every pair in a set. Note that the work done is the product of the two counts, so a 1000 by 1000 nesting is a million passes. Give the counters real names instead of i and j as soon as there is more than one.

Example · csharp
// The outer loop walks rows, the inner one walks columns.
// The inner loop runs all the way through on every outer pass.
for (int row = 1; row <= 3; row++)
{
    string line = "";
    for (int col = 1; col <= 3; col++)
    {
        // ,3 right-aligns the number in a field three characters wide.
        line += $"{row * col,3}";
    }

    Console.WriteLine(line);
}

// Output:
//   1  2  3
//   2  4  6
//   3  6  9

do-while, where the first pass is unconditional

This is the real test for picking do over while: ask whether the body must run before the condition can be judged. Retrying a request, prompting until the input is valid, and consuming a first chunk before checking for more all fit. If the body might need to be skipped entirely, use while instead.

Example · csharp
int value = 40;
int steps = 0;

// Halve the value until it reaches 1. The first halving happens
// whatever the starting value is, which is what do expresses.
do
{
    value /= 2;   // integer division: 40, 20, 10, 5, 2, 1
    steps++;
}
while (value > 1);

Console.WriteLine($"steps: {steps}");

// Output:
// steps: 5

Discussion

  • Be the first to comment on this lesson.