Codectionary / Developer documentation / C#

foreach & IEnumerable

foreach is C#'s dedicated loop for iterating over any collection that implements IEnumerable<T> - which includes arrays, List<T>, Dictionary<TKey,TValue>, and virtually every built-in collection. Behind the scenes, foreach uses an enumerator (via GetEnumerator()) to walk through items one at a time. Any custom class can support foreach by implementing IEnumerable<T> itself.

Syntax

foreach (Type item in collection) {\n  // code\n}

Examples

Basic foreach Usage

Iterating over different built-in collection types with the same syntax.

List<string> names = new List<string> { "Fola", "Zain", "Jamal" };

foreach (string name in names)
{
    Console.WriteLine(name);
}

int[] numbers = { 1, 2, 3 };
foreach (int n in numbers)
{
    Console.WriteLine(n * n);
}

foreach with var

Using var lets the compiler infer the element type, useful when working with complex generic types.

Dictionary<string, int> scores = new Dictionary<string, int>
{
    ["Alice"] = 85,
    ["Bob"] = 92
};

foreach (var entry in scores)  // type inferred as KeyValuePair<string, int>
{
    Console.WriteLine($"{entry.Key}: {entry.Value}");
}

Implementing IEnumerable in a Custom Class

Making a custom class support foreach by implementing IEnumerable<T>, often with a yield return generator method.

public class NumberRange : IEnumerable<int>
{
    private int _start, _end;
    public NumberRange(int start, int end) { _start = start; _end = end; }

    public IEnumerator<int> GetEnumerator()
    {
        for (int i = _start; i <= _end; i++)
            yield return i;
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        => GetEnumerator();
}

foreach (int n in new NumberRange(1, 5))
{
    Console.WriteLine(n);  // 1, 2, 3, 4, 5
}

Best practices

  • Use foreach by default for reading through a collection - it is safer and more readable than a manual indexed loop
  • Don't modify a collection's structure (adding/removing items) while iterating over it with foreach - it throws an InvalidOperationException
  • Implement IEnumerable<T> on a custom class when it genuinely represents a collection of things, so it works naturally with foreach and LINQ
  • Use yield return inside GetEnumerator() (or any iterator method) for a concise way to implement custom iteration logic

At a glance

Purpose
Applications on the .NET platform
File extension
.cs
Runs in
.NET runtime
Usually used with
.NET SDK and libraries

Specifications & further reading

Related C# documentation

List<T>
List<T> is a resizable, generic collection from System.Collections.Generic, and the most commonly used collection type in C#. Unlike a plain array, a List<T> automatically grows as elements are added, and it provides a rich set of methods for adding, removing, searching, and sorting. The <T> means a List can be strongly typed to hold any specific type, like List<string> or List<int>.
Dictionary<TKey, TValue>
Dictionary<TKey, TValue> stores data as key-value pairs, offering fast average-case lookup, insertion, and deletion by key, backed by a hash table. Keys must be unique - adding a value with an existing key throws an exception, while indexer assignment (dict[key] = value) overwrites it instead. Dictionary does not guarantee any particular iteration order.
Queue<T> & Stack<T>
Queue<T> is a first-in-first-out (FIFO) collection - items are added with Enqueue() and removed with Dequeue(), just like a real-world line. Stack<T> is last-in-first-out (LIFO) - items are added with Push() and removed with Pop(), like a stack of plates. Both are useful for specific processing orders where a general-purpose List<T> would require extra bookkeeping.
HashSet<T>
HashSet<T> is a collection that stores unique elements with no guaranteed ordering, backed by a hash table. Adding a duplicate element has no effect, since HashSet automatically enforces uniqueness. It provides very fast average-case performance for adding, removing, and checking membership, and offers built-in set operations like union, intersection, and difference.