13

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?

nan
  • 19,595
  • 7
  • 48
  • 80

2 Answers2

42

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);
Maciej Hehl
  • 7,895
  • 1
  • 22
  • 23
Timwi
  • 65,159
  • 33
  • 165
  • 230
1

You can also make your cars private, and add a public or internal property, because tomorrow in your garage you will have Employees and Tools and so on, so your enumerate will make no sens. So with the followings you have no more code to provide :

private List<Car> m_Cars=new List<Car>();
private List<Employee> m_Employees=new List<Employee>();
public  List<Car> Cars { get { return m_Cars; } }
internal List<Employee> Employees { get { return m_Employees; } }

So you can use foreach, on cars, employees like this:

var redCars = myGarage.Cars.Where(car => car.Color == CarColor.Red);
var Employees1 = myGarage.Employees.Where(e => e.Name == 'xxx');
bruno leclerc
  • 333
  • 2
  • 9