Skip to content
Theory · Conditions and loops · lesson 11 of 13

Nested loops

A runner is training for a race, and the coach has a plan for several days: three laps every day. In a notebook, the runner marks "day, lap" pairs: day 1, lap 1; day 1, lap 2; and so on. When the day's laps are done, the next day comes, and the lap count starts over.

Such a plan is a loop inside a loop. The outer loop goes through the days, and a nested loop goes through the laps of one day:

C#
for (int day = 1; day <= 2; day++)
{
    for (int lap = 1; lap <= 3; lap++)
    {
        Console.WriteLine(day + " " + lap);
    }
}
// 1 1
// 1 2
// 1 3
// 2 1
// 2 2
// 2 3

The expression day + " " + lap glues a number, a space and the second number into one string. Let's take apart what happens:

  1. The outer loop starts with day = 1.
  2. The inner loop runs lap from 1 to 3, and the program prints 1 1, 1 2, 1 3.
  3. The inner loop is done, and the outer one runs its step: day becomes 2.
  4. The inner loop starts over, with lap = 1, and prints 2 1, 2 2, 2 3.
  5. The outer step gives day = 3, the condition day <= 2 is false, and both loops are over.

The inner loop runs in full on every iteration of the outer one. That is why its body runs 2 * 3, which is six, times: the number of outer iterations multiplied by the number of inner ones.

Interviewers bring this up when they talk about how fast a program is. If both loops go through n values, the body runs n * n times: for n = 1000, that is already a million iterations.

The inner loop depends on the outer one

The inner loop's condition can use the outer loop's variable. That is how you draw a triangle of stars, where row number row has exactly row stars:

C#
for (int row = 1; row <= 4; row++)
{
    for (int k = 1; k <= row; k++)
    {
        Console.Write("*");
    }
    Console.WriteLine();
}
// *
// **
// ***
// ****

Let's go step by step:

  1. The outer loop goes through the rows: row from 1 to 4.
  2. The inner loop prints stars with Console.Write, and they all stay on one line. The condition k <= row gives as many stars as the row's number.
  3. Console.WriteLine() with empty parentheses stands in the outer loop, after the inner one, and ends the line.

This is how you solve tasks that need every pair of values: a multiplication table, every combination of two numbers.

break in a nested loop

break ends only the nearest loop, the one it stands in. If it is inside a nested loop, the outer loop runs the rest of its body after the inner loop and then moves on to its next iteration.

This is where the training analogy breaks down. The coach can cancel the whole plan at once, but break has no such power: from the inner loop it cancels only today's laps, and the next day still comes.

To leave both loops at once, you set up a bool flag variable and check it in the outer loop's condition. Let's find the first pair of numbers from 1 to 3 whose product is 6:

C#
bool found = false;

for (int a = 1; a <= 3 && !found; a++)
{
    for (int b = 1; b <= 3; b++)
    {
        if (a * b == 6)
        {
            Console.WriteLine(a + " " + b); // 2 3
            found = true;
            break;
        }
    }
}

Let's see how both loops end:

  1. While no pair has been found, found is false, and the outer loop's condition depends only on a.
  2. With a = 2 and b = 3, the product is 6: the program prints 2 3 and stores true in found.
  3. break ends the inner loop.
  4. The outer loop runs its step a++ and checks the condition: !found is now false, and the outer loop ends too.

Without && !found, the outer loop would move on to a = 3 and print another pair, 3 2. Interviewers sometimes ask how to leave two loops at once, and a flag in the outer loop's condition is one of the answers.

Common mistake

The nested loop uses the same variable name as the outer one:

C#
for (int i = 1; i <= 2; i++)
{
    for (int i = 1; i <= 3; i++) // ✗
    {
        Console.Write(i);
    }
}
TEXT
error CS0136: A local or parameter named 'i' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter

The program does not compile. The inner loop stands inside the outer one, where the variable i already exists. A second declaration with the same name would make it unclear which i is meant, and C# forbids it. Give the inner loop's variable its own name, such as j.

Key points

  • A nested loop runs in full on every iteration of the outer one: with 2 days of 3 laps, its body runs 2 * 3 times.
  • The inner loop's condition can use the outer loop's variable.
  • break ends only the nearest loop; to leave both, check a flag in the outer loop's condition.
  • A nested loop's variable needs its own name: you cannot reuse the outer loop variable's name.