1. Intro
Let's start with a question: why would you ever need to put one loop inside another? Well, a lot of times our data or tasks aren't just in a straight line, but in a table, a grid, or even a multi-dimensional structure. Say you want to print a multiplication table, walk through a 2D array, or count intersections between all pairs of elements. One loop just won't cut it here — you need a loop inside a loop.
In programming, a nested loop is like having two alarm clocks: the outer one starts ringing, and inside it, another one goes off every time the first one is active. So, while one "outer" iteration is running, the inner one goes through its whole cycle (and does it again and again for every outer iteration).
A good example is hours and minutes. Hours are the outer loop from 0 to 23, minutes are the inner loop from 0 to 59. For every change in the outer loop, the inner loop gets to run through all its values.
2. Nested Loops Syntax
In C#, the syntax for nested loops is just like regular loops — you just write one loop inside the body of another. Let's check out some examples with for and while:
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
Console.Write($"{i},{j} ");
}
Console.WriteLine();
}
Here, the outer loop controls the variable i (from 0 to 2), and the inner one — variable j (from 0 to 3). For every value of i, the inner loop goes all the way from j=0 to j=3. If you run this code, you'll see a nice little coordinate table:
0,0 0,1 0,2 0,3
1,0 1,1 1,2 1,3
2,0 2,1 2,2 2,3
Here's a similar example using while:
int i = 0;
while (i < 3)
{
int j = 0;
while (j < 4)
{
Console.Write($"{i},{j} ");
j++;
}
Console.WriteLine();
i++;
}
Heads up: inside every run of the outer loop, the inner loop variable (j) needs to be re-initialized, or you'll only see one row!
3. Examples of Nested Loops in Action
Example 1: Printing a Chessboard (8x8)
Let's make our first task to print a classic chessboard with black and white squares (# for black, _ for white). We'll do it with nested for loops:
for (int row = 0; row < 8; row++)
{
for (int col = 0; col < 8; col++)
{
if ((row + col) % 2 == 0)
Console.Write("_");
else
Console.Write("#");
}
Console.WriteLine();
}
Result:
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
Important: nesting makes sure that for every row (row) we go through all the columns (col). Without nesting, you wouldn't get a board — just a single row or column.
Example 2: Multiplication Table
One of the classic uses for nested loops! Let's print a multiplication table from 1 to 9:
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
Console.Write($"{i * j,3} ");
}
Console.WriteLine();
}
The formatting ${i * j,3} adds spaces so the table looks neat.
Result:
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
...
9 18 27 36 45 54 63 72 81
4. Nested Loops and How to Control Them — Gotchas
About break and continue in Nested Loops
This is where a lot of newbies get tripped up! If you use break or continue in the inner loop, they only affect that loop. The outer one just keeps going like nothing happened.
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
if (j == 3)
break; // we only jump out of the inner loop!
Console.Write($"{i},{j} ");
}
Console.WriteLine();
}
Result:
0,0 0,1 0,2
1,0 1,1 1,2
2,0 2,1 2,2
If you need to break out of both nested loops at once (like, you want to stop searching as soon as you find a match in a table), people usually use a flag or a special trick (like return — if everything's inside a function).
5. Visualizing Nested Loops
Sometimes it's tough to "see" the order in which nested loops run. Check out this flowchart:
In table form — how many total iterations will there be if i goes from 1 to 3, and j from 1 to 4?
| i | j (loops for each i) | Inner loop iterations |
|---|---|---|
| 1 | 1, 2, 3, 4 | 4 |
| 2 | 1, 2, 3, 4 | 4 |
| 3 | 1, 2, 3, 4 | 4 |
| Total: 3 × 4 = 12 |
6. Mistakes and Pitfalls When Working with Nested Loops
A common mistake is messing up the initialization of the inner loop variable. For example, declaring it outside the outer loop and not resetting it every time. As a result, the inner loop might not run at all, or run wrong.
int j = 0;
for (int i = 0; i < 3; i++)
{
while (j < 4) // Oops! j might already be 4 after the first iteration.
{
Console.Write($"{i},{j} ");
j++;
}
Console.WriteLine();
}
Here, the loop will only run once. Don't forget to initialize inner loop variables inside the outer loop!
Also, if you accidentally write two nested loops with the same variable name, the compiler will yell at you: the variable is already defined.
for (int i = 0; i < 3; i++)
{
for (int i = 0; i < 3; i++)
{
Console.Write($"{i},{i} ");
}
Console.WriteLine();
}
GO TO FULL VERSION