Skip to content
Theory · Arrays · lesson 3 of 9

The foreach loop

In the previous lesson a for loop walked through an array by its indexes. Often you don't need the index: you only want to see what each element holds. And one call to Console.WriteLine will not print an array:

C#
int[] scores = [90, 75, 88];
Console.WriteLine(scores); // System.Int32[]
foreach (int score in scores)
{
    Console.WriteLine(score);
}
// 90
// 75
// 88

Console.WriteLine(scores) prints the name of the type, not the elements: System.Int32[] is what .NET calls an array of int. To see the contents, you walk through the array element by element.

Think back to the row of lockers. A foreach loop is a walk along the row from the first locker to the last. At each door you look inside and do the same thing with whatever is there. You don't need the locker numbers for that.

How foreach works

The header foreach (int score in scores) reads "for each score in scores". It has three parts:

  • int score is the loop variable: on each iteration it holds a copy of the next element;
  • in is the keyword between the variable and the array;
  • scores is the array the loop walks through.

The body runs once for each element, in order from index 0 to the last one. An array of three elements gives three iterations. foreach never goes past the end of the array: it knows where the row ends.

The sum and the largest element

Walking through the elements is the core of many array tasks:

  • adding up a sum;
  • finding the largest value;
  • counting the elements that fit.
C#
int[] temps = [-3, -1, -7, -4];
int sum = 0;
int max = temps[0];
foreach (int t in temps)
{
    sum += t;
    if (t > max)
    {
        max = t;
    }
}
Console.WriteLine(sum); // -15
Console.WriteLine(max); // -1

Let's see what the program does:

  1. The variable sum starts at zero, and each iteration adds the next temperature to it.
  2. max starts at the first element, temps[0].
  3. If the next element is greater than max, it becomes the new maximum.
  4. After the loop, sum holds -15 and max holds -1.

Why does max start at temps[0] and not at zero? All the temperatures here are negative. Start at zero, and no element is ever greater, so the program prints 0, a number the array does not even hold. Interviewers like to check this trap with the "find the maximum" task.

foreach or for

You pick foreach when you need only the values of the elements. A for loop is needed in two cases:

  • you need the index itself: to print an element's number or to compare neighbors a[i] and a[i + 1];
  • you need to write new values into the elements.

In the second case you cannot do without for: the foreach loop variable is read-only, so elements are changed by index:

C#
int[] scores = [90, 75, 88];
for (int i = 0; i < scores.Length; i++)
{
    scores[i] = scores[i] + 5;
}
Console.WriteLine(string.Join(", ", scores)); // 95, 80, 93

string.Join(", ", scores) glues the elements of the array into one string and puts its first argument between them, here a comma and a space. It is a handy way to print a whole array.

Here the locker picture stops working. Standing at an open door, you can swap what is in the locker. The foreach variable is a copy of what the element holds, not an open door: you cannot swap the contents through it.

Common mistake

Someone tried to change the elements through the foreach variable:

C#
int[] scores = [90, 75, 88];
foreach (int score in scores)
{
    score = score + 5; // ✗
}
TEXT
error CS1656: Cannot assign to 'score' because it is a 'foreach iteration variable'

The program does not compile: the foreach loop variable is read-only. To change the elements, walk through the array with a for loop by index, as in the example above.

Key points

  • foreach (int score in scores) goes through every element of the array in order, with no indexes and no way past the end.
  • The foreach loop variable gets a copy of the element and is read-only.
  • To change elements or to know the index, you need a for loop.
  • Console.WriteLine(scores) prints the type System.Int32[], while string.Join(", ", scores) prints the elements separated by commas.