nan nan - 17 days ago 6
C# Question

Overload indexer to have foreach'able class

I tried to do something like this but this doesn't work:

class Garage
{
private List<Car> cars = new List<Car>();

public Car this[int i]
{
get { return cars[i]; }
}
//...
}

Garage g = new Garage();
//get CS1579 - no GetEnumerator definition
foreach (Car c in g)
{
//...
}


As MSDN says indexers can be overloaded, so I decided to ask experts here. How to overload indexers to cooperate with
foreach
loop?

Answer

foreach has nothing to do with indexers. You need to declare a GetEnumerator method that returns an enumerator for the collection. (While you’re at it, it may be wise to implement the IEnumerable<Car> interface as well, which provides this method.) In your particular case, you can do it easily like this:

class Garage : IEnumerable<Car>
{
    private List<Car> cars = new List<Car>();

    public Car this[int i]
    {
        get { return cars[i]; }
    }

    // For IEnumerable<Car>
    public IEnumerator<Car> GetEnumerator() { return cars.GetEnumerator(); }

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

A huge benefit of implementing the IEnumerable<Car> interface is that you can use all the LINQ extension methods, e.g. Where and Select, for example:

var redCars = myGarage.Where(car => car.Color == CarColor.Red);