Why loop over an array
An array holds a sequence of items, and a very common job is to do something with each one: print it, add it to a total, check it against a condition. A loop lets you write that action once and run it for every item. C# has several loops. For visiting every element of an array in order, the cleanest is foreach.
The foreach loop
string[] fruits = {"banana", "orange", "pear", "kiwi"};
foreach (string fruit in fruits) {
Console.WriteLine("I eat " + fruit);
}
The output is:
I eat banana
I eat orange
I eat pear
I eat kiwi
The loop header has four parts:
foreachstarts the loop.string fruitis the loop variable. It holds a different element on each pass: first"banana", then"orange", and so on.inseparates the loop variable from the collection. C# uses the wordinhere, not a colon.fruitsis the collection to walk through.
The statements between the braces are the loop body. It runs once per element, and the loop ends after the last one. You never write an index, so there is no counter to start, increase or compare against the length.
foreach versus for
In C#, the keyword for is the counting loop. It is the right choice when you need the index itself:
for (int i = 0; i < fruits.Length; i++) {
Console.WriteLine(i + ": " + fruits[i]);
}
// 0: banana
// 1: orange
// 2: pear
// 3: kiwi
Note i < fruits.Length: the last valid index is Length - 1, so a condition of i <= fruits.Length would read one element past the end and throw an IndexOutOfRangeException. When you only need the values, foreach is shorter and removes that risk.
A syntax from other languages sometimes appears in ported code: for (string fruit : fruits). That is not valid C#. The loop over elements is foreach (string fruit in fruits).
What you can and can't do in the loop
- Type. The loop variable's type must fit the elements. You can write
varand let the compiler infer it:foreach (var fruit in fruits). - The loop variable is read-only. Assigning to it, as in
fruit = "x";, is a compile error. It is a copy of the element for that pass and doesn't write back into the array. - Empty arrays are fine. The body simply never runs.
- Other collections work too.
foreachalso walks aList<T>, the characters of astringand many other collections. Changing the size of a list while you loop over it throws anInvalidOperationException.
The exercise, step by step
The lesson gives you an array of friends and asks you to greet each one.
- Write the loop. Use
foreachwith astringvariable namedfriend, looping through thefriendsarray. Open a brace for the body. - Print the greeting inside the body. For each
friend, callConsole.WriteLine("Hey, " + friend + "!"). The+operator joins strings, andWriteLineadds the line break after each greeting.
string[] friends = {"Andy", "Mary", "John"};
foreach (string friend in friends) {
Console.WriteLine("Hey, " + friend + "!");
}
It prints:
Hey, Andy!
Hey, Mary!
Hey, John!
Common mistakes
- Using a colon instead of
in.foreach (string friend : friends)doesn't compile. - Using the wrong variable inside the body. The loop variable's name is the one in the header. Writing
friendsin the message would try to join a whole array into the text. - Printing outside the braces. A statement after the closing brace runs once, after the loop is finished. Without braces, a
foreachruns only the single statement right after it, so always use braces. - Forgetting the space or punctuation in the text.
"Hey, "has a space after the comma, and the exclamation mark is part of the expected output. - Trying to change elements through the loop variable. To modify an array in place, use a
forloop with an index.
Key takeaways
foreach (Type item in collection) { ... }runs the body once for each element, in order.- The loop variable takes each element's value and is read-only.
- Use
forwith an index when you need positions or want to change elements.