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:
int[] scores = [90, 75, 88];
Console.WriteLine(scores); // System.Int32[]
foreach (int score in scores)
{
Console.WriteLine(score);
}
// 90
// 75
// 88Console.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 scoreis the loop variable: on each iteration it holds a copy of the next element;inis the keyword between the variable and the array;scoresis 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.
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); // -1Let's see what the program does:
- The variable
sumstarts at zero, and each iteration adds the next temperature to it. maxstarts at the first element,temps[0].- If the next element is greater than
max, it becomes the new maximum. - After the loop,
sumholds-15andmaxholds-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]anda[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:
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, 93string.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:
int[] scores = [90, 75, 88];
foreach (int score in scores)
{
score = score + 5; // ✗
}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
foreachloop variable gets a copy of the element and is read-only. - To change elements or to know the index, you need a
forloop. Console.WriteLine(scores)prints the typeSystem.Int32[], whilestring.Join(", ", scores)prints the elements separated by commas.