Skip to main content

C# Foreach Loop

Introduction

The foreach loop is one of the most convenient control flow mechanisms in C#, specifically designed for iterating through elements in a collection. Unlike a for loop where you manually control the iteration, a foreach loop automatically steps through all items in a collection such as arrays, lists, dictionaries, or any object that implements the IEnumerable or IEnumerable<T> interface.

The foreach loop is particularly helpful for beginners as it simplifies the process of collection traversal by eliminating the need for index management or explicit bounds checking.

Basic Syntax

The syntax of a foreach loop is straightforward:

csharp
foreach (type element in collection)
{
// Code to execute for each element
}

Where:

  • type is the data type of the elements in the collection
  • element is a variable that represents the current item being processed
  • collection is the collection being iterated through

Simple Example: Iterating Through an Array

Let's start with a basic example of using foreach to iterate through an array of integers:

csharp
using System;

class Program
{
static void Main()
{
// Define an array of integers
int[] numbers = { 1, 2, 3, 4, 5 };

// Use foreach to iterate through the array
Console.WriteLine("Numbers in the array:");
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}

Output:

Numbers in the array:
1
2
3
4
5

In this example, the foreach loop automatically iterates through each element in the numbers array. For each iteration, the current element is assigned to the number variable, which we can then use inside the loop body.

Key Characteristics of the Foreach Loop

1. Read-Only Access

An important limitation to understand is that the foreach loop provides read-only access to the collection elements. You cannot modify the collection element through the iteration variable:

csharp
int[] numbers = { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
// This will cause a compilation error
// number = number * 2;
}

If you need to modify the elements, you should use a regular for loop with index access, or store the modified values in a new collection.

2. No Index Access

Unlike the for loop, the foreach loop does not provide direct access to the index of the current element:

csharp
string[] fruits = { "Apple", "Banana", "Cherry" };

// If you need indices with foreach, you need to track them manually
int index = 0;
foreach (string fruit in fruits)
{
Console.WriteLine($"Fruit at index {index}: {fruit}");
index++;
}

Output:

Fruit at index 0: Apple
Fruit at index 1: Banana
Fruit at index 2: Cherry

Iterating Through Different Collection Types

The foreach loop works with any collection type that implements the IEnumerable interface. Let's explore a few examples:

Lists

csharp
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<string> cities = new List<string>
{
"New York",
"London",
"Tokyo",
"Paris",
"Sydney"
};

Console.WriteLine("Cities around the world:");
foreach (string city in cities)
{
Console.WriteLine(city);
}
}
}

Output:

Cities around the world:
New York
London
Tokyo
Paris
Sydney

Dictionaries

When iterating through a dictionary with foreach, each element is a key-value pair:

csharp
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
Dictionary<string, int> ages = new Dictionary<string, int>
{
{ "John", 28 },
{ "Mary", 24 },
{ "Steve", 32 },
{ "Lisa", 26 }
};

foreach (KeyValuePair<string, int> person in ages)
{
Console.WriteLine($"{person.Key} is {person.Value} years old");
}

// You can also use var for simpler code
Console.WriteLine("\nUsing var keyword:");
foreach (var person in ages)
{
Console.WriteLine($"{person.Key} is {person.Value} years old");
}

// If you only need the keys
Console.WriteLine("\nOnly names:");
foreach (string name in ages.Keys)
{
Console.WriteLine(name);
}

// If you only need the values
Console.WriteLine("\nOnly ages:");
foreach (int age in ages.Values)
{
Console.WriteLine(age);
}
}
}

Output:

John is 28 years old
Mary is 24 years old
Steve is 32 years old
Lisa is 26 years old

Using var keyword:
John is 28 years old
Mary is 24 years old
Steve is 32 years old
Lisa is 26 years old

Only names:
John
Mary
Steve
Lisa

Only ages:
28
24
32
26

Strings

Since strings in C# are collections of characters, you can use foreach to iterate through each character in a string:

csharp
using System;

class Program
{
static void Main()
{
string message = "Hello";

Console.WriteLine("Characters in the message:");
foreach (char c in message)
{
Console.WriteLine(c);
}
}
}

Output:

Characters in the message:
H
e
l
l
o

Real-World Examples

Example 1: Processing Student Grades

Let's create a more practical example where we use a foreach loop to calculate the average grade of students:

csharp
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
Dictionary<string, List<double>> studentGrades = new Dictionary<string, List<double>>
{
{ "Alice", new List<double> { 92.5, 88.0, 95.5, 90.0 } },
{ "Bob", new List<double> { 85.0, 87.5, 77.0, 92.0 } },
{ "Charlie", new List<double> { 72.0, 81.5, 86.0, 78.5 } }
};

foreach (var student in studentGrades)
{
double sum = 0;
foreach (double grade in student.Value)
{
sum += grade;
}

double average = sum / student.Value.Count;
Console.WriteLine($"{student.Key}'s average grade: {average:F1}");
}
}
}

Output:

Alice's average grade: 91.5
Bob's average grade: 85.4
Charlie's average grade: 79.5

This example shows how foreach loops can be nested to process more complex data structures.

Example 2: Filtering a Collection

Here's how you could use a foreach loop alongside a List to filter elements from a collection:

csharp
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<int> allNumbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<int> evenNumbers = new List<int>();

foreach (int number in allNumbers)
{
if (number % 2 == 0)
{
evenNumbers.Add(number);
}
}

Console.WriteLine("Even numbers:");
foreach (int number in evenNumbers)
{
Console.Write($"{number} ");
}
}
}

Output:

Even numbers:
2 4 6 8 10

Using Foreach with Custom Classes

The foreach loop can also be used with your custom classes as long as they implement the IEnumerable or IEnumerable<T> interface:

csharp
using System;
using System.Collections;
using System.Collections.Generic;

class BookCollection : IEnumerable<Book>
{
private List<Book> books = new List<Book>();

public void AddBook(Book book)
{
books.Add(book);
}

public IEnumerator<Book> GetEnumerator()
{
return books.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

class Book
{
public string Title { get; set; }
public string Author { get; set; }

public Book(string title, string author)
{
Title = title;
Author = author;
}

public override string ToString()
{
return $"{Title} by {Author}";
}
}

class Program
{
static void Main()
{
BookCollection myBooks = new BookCollection();
myBooks.AddBook(new Book("The Great Gatsby", "F. Scott Fitzgerald"));
myBooks.AddBook(new Book("To Kill a Mockingbird", "Harper Lee"));
myBooks.AddBook(new Book("1984", "George Orwell"));

Console.WriteLine("My Book Collection:");
foreach (Book book in myBooks)
{
Console.WriteLine(book);
}
}
}

Output:

My Book Collection:
The Great Gatsby by F. Scott Fitzgerald
To Kill a Mockingbird by Harper Lee
1984 by George Orwell

Foreach vs. For Loop: When to Use Each

While foreach is simpler and cleaner, there are situations where a traditional for loop might be more appropriate:

  1. Use foreach when:

    • You need to process all elements in a collection
    • You don't need to modify the elements
    • You don't need the index of the current element
    • You want cleaner, more readable code
  2. Use for when:

    • You need to modify the elements in the collection
    • You need access to the element index
    • You need to skip elements or process them in a specific order
    • You need more control over the iteration process

Summary

The foreach loop is a powerful and elegant feature in C# that simplifies collection traversal. Its main advantages are:

  • Simplicity and readability
  • No need for explicit indexing or bounds checking
  • Works with any collection that implements IEnumerable
  • Helps prevent common errors like index out-of-bounds

However, it also has some limitations, such as read-only access to collection elements and no direct access to element indices.

Understanding when and how to use the foreach loop is an essential skill for any C# programmer, as it makes your code cleaner, more readable, and less prone to errors.

Practice Exercises

  1. Create a program that uses a foreach loop to find the maximum value in an array of integers.
  2. Write a program that uses a foreach loop to count the number of vowels in a string.
  3. Create a program with a List of student objects (with properties like Name and Grade), and use a foreach loop to find all students who received an A (grade >= 90).
  4. Write a program that uses nested foreach loops to print out all combinations of two lists.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)