C# basics: foreach loops

foreach loops are used to loop through collections of objects. C# has many standard type of loop functions, but the foreach loop is a special case. It can however be broken down to basic components to understand how it works. Imagine you have an array of cars that you iterate with a foreach loop:

//The car class
class Car{
  public int CarID {get;set;}
  public string Model {get;set;}
}

//Create an array of cars
public Car[] Cars = new Car[] {
  new Car { CarID = 1, Model = "Volvo"},
  new Car { CarID = 2, Model = "Mercedes"}
}

//Loop through the array
foreach(var Car in Cars)
{
  Console.WriteLine($"Car with ID {Car.CarID} is a {Car.Model}.");
}

// Car with ID 1 is a Volvo
// Car with ID 2 is a Mercedes

You get the Car objects one at a time, but under the hood more things are happening. The code invokes the method GetEnumerator() on the array which returns an object designed to iterate collections, let’s call it enum. This object must have a property named Current indicating the current object, and a method bool MoveNext(). The foreach loop could instead be written like this:

var enum = Cars.GetEnumerator();

while(enum.MoveNext())
{
  Var Car = enum.Current();

  // Start of code inside foreach block
  Console.WriteLine($"Car with ID {Car.CarID} is a {Car.Model}.");
}

Implementation

You can implement this functionality in your own class as well. Although the foreach loop doesn’t require any special function of the method MoveNext() and property Current of the object returned by GetEnumerator(), the most common case is to loop through each item and return false when the end is reached, keeping track of items with an index.

class CarEnumerator
{
  //MoveNext is invoked at the start of the loop, so begin the index at -1 to start at 0
  private int index = -1;
  private readonly Car[] Cars;

  //The Cars array is given during construction
  public CarEnumerator(Car[] Cars)
  {
    this.Cars = Cars;
  }

  //Move next advances the index by one and returns true if the end of the collection is not reached
  //When index >= Cars.Length it will return false, and the while-loop will not continue
  public bool MoveNext()
  {
    index ++;
    return (index < Cars.Length)
  }

  //The get method of the Current property returns the object at the current index position
  public Car Current
  {
    get{
      return Cars[index]
    }
  }
}

The actual method GetEnumerator() resides in a separate class, which also holds the collection.

class CarList
{
  Car[] Cars;

  public CarList(Car[] Cars)
  {
    this.Cars = Cars;
  }

  public CarEnumerator GetEnumerator()
  {
    return new CarEnumerator(Cars);
  }
}

In practice

This was a brief overview of how the foreach loop works. In practice you should implement the interface IEnumerable and IEnumerator when creating custom implementations for your class.

Leave a comment

Design a site like this with WordPress.com
Get started