Share via


A way to do named indexers.

In this entry on Ladybug, a customer asked for named indexers in C#.

Here’s one way to get it:

      class Car

      {

            object[] wheels;

            public WheelsHelper Wheels { get { return new WheelsHelper(this); } }

            public class WheelsHelper

            {

                  readonly Car _outer;

                  public WheelsHelper(Car mc) { this._outer = mc; }

                  public object this[int index] { get { return this._outer.wheels[index]; } }

            }

      }

You use it in the obvious way:

            Car car = ...;

            car.Wheels[0];

Comments

  • Anonymous
    July 16, 2004
    meh.. the provided solution on msdn for 2.0 is a bit twacky also imho..

    public class Car
    {
    protected List<Wheel> _wheels = new List<Wheel>();
    protected List<Seat> _seats = new List<Seat>();

    public List<Wheel> Wheels
    {
    get { return _wheels; }
    }

    public List<Seat> Seats
    {
    get { return _seats; }
    }
    }

    Car.Wheels[0]; // Returns the wheel at index 0
    Car.Seats[0]; // Returns the seat at index 0

    Can implement this pattern in 1.0 also similarly to what you have done

    public class Car
    {
    protected ArrayList _wheels = new ArrayList();
    protected ArrayList _seats = new ArrayList();

    public ArrayList Wheels
    {
    get { return _wheels; }
    }

    public ArrayList Seats
    {
    get { return _seats; }
    }
    }

    or for 1.0 create your own WheelCollection and SeatCollection classes...

    public WheelCollection : ICollection {...} // implements public Wheel this[int index];
  • Anonymous
    July 16, 2004
    um.. duh?

    class Car
    {
    object[] wheels;
    object[] seats;

    public object[] Wheels
    {
    get { return wheels; }
    }

    public object[] Seats
    {
    get { return seats; }
    }
    }
  • Anonymous
    July 16, 2004
    what am I missing?
  • Anonymous
    July 16, 2004
    Mutability. Law of Demeter. Encapsulation. Verbosity.
  • Anonymous
    July 16, 2004
    You're violating Demeter as well by operating on what was returned by Wheels. But mutability is probably the biggest concern because it doesn't appear that you intended for these to be editable.

    I think the helper solution is not bad except:

    1) A new helper is created every time you access Wheels. Since they should be immutable it would be better to share them.

    2) The namespace gets polluted with this extra public class.
  • Anonymous
    July 16, 2004
    By the way, "Verbosity." is a joke. Get it?
  • Anonymous
    July 16, 2004
  1. This is the simplest way I know to write the code. If you take this code, measure your performance, and optimize as needed.

    "Make it work, make it right, make it fast"

    2. Well, kinda. It's a nested class, so it only shows up as a member of 'Car'.

    I'm a big fan of nested classes.

    http://blogs.msdn.com/jaybaz_ms/archive/2004/07/02.aspx
    http://blogs.msdn.com/jaybaz_ms/archive/2004/04/28/122401.aspx#126071
    http://blogs.msdn.com/jaybaz_ms/archive/2004/02/20/77385.aspx
  • Anonymous
    July 16, 2004
    Isn't that what the System.Runtime.CompilerServices.IndexerName does?

  • Anonymous
    July 16, 2004
    I'm a big fan of nested classes too. I just wish there was a good way to hide one in this case. If there had already been some public class or interface that worked here, we could have declared the return type to be that class and made the inner class implementation private. Maybe it just needs to be stealthy enough for Intellisense not to pick up it.

  • Anonymous
    July 16, 2004
    Singletons aren't just for performance. Someone using this is going to have the possibly unexpected behavior that car.Wheels == car.Wheels is false. You can't use it in a data structure that relies on searching. It's possible to implement Equals and GetHashCode to avoid this but that's more work than a singleton probably.

  • Anonymous
    July 16, 2004
    One way to avoid defining a new public type for each situation is to create a non-nested interface that you return in all different instances. Then the CWheelsHelper class can be private.

    interface IIndexed<T, I> { T this[I index] { get; set;} }

    ...

    public IIndexed<object, int> Wheels { get { return new WheelsHelper(this); } }

    I still haven't provided a good answer about the singleton issue.

  • Anonymous
    July 16, 2004

    Mutability... good point.. now that you mention that I see how the posted generic response works better...

  • Anonymous
    July 19, 2004
    I just want to add more weight to Christoffer Skjoldborg's comment. I'm suprised more people aren't aware of how Indexers are implemented in MSIL.

    Try writing Indexers with different names in C#, then use them from VB.Net - and vice versa. That's what I did when I was learning .Net.

  • Anonymous
    July 20, 2004
    The comment has been removed

  • Anonymous
    June 09, 2009
    PingBack from http://greenteafatburner.info/story.php?id=1589

  • Anonymous
    June 14, 2009
    PingBack from http://adirondackchairshub.info/story.php?id=3186