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
- 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 removedAnonymous
June 09, 2009
PingBack from http://greenteafatburner.info/story.php?id=1589Anonymous
June 14, 2009
PingBack from http://adirondackchairshub.info/story.php?id=3186