Reputation: 7908
I'm trying to implement a family of classes who keep track of how many instances exist on a per-class basis. Because all of these classes have this behavior, I'd like to pull it out into a single superclass so I don't have to repeat the implementation with each class. Consider the following code:
class Base
{
protected static int _instances=0;
protected int _id;
protected Base()
{
// I would really like to use the instances of this's class--not
// specifically Base._instances
this._id = Base._instances;
Base._instances++;
}
}
class Derived : Base
{
// Values below are desired,
// not actual:
Derived d1 = new Derived(); // d1._id = 0
Derived d2 = new Derived(); // d2._id = 1
Derived d3 = new Derived(); // d3._id = 2
public Derived() : base() { }
}
class OtherDerived : Base
{
// Values below are desired,
// not actual:
OtherDerived od1 = new OtherDerived(); // od1._id = 0
OtherDerived od2 = new OtherDerived(); // od2._id = 1
OtherDerived od3 = new OtherDerived(); // od3._id = 2
public OtherDerived() : base() { }
}
How can I achieve a per-class instance counter (one that is separate from the base class's counter)? I've tried mixing static & abstract (doesn't compile). Please advise.
Upvotes: 0
Views: 389
Reputation: 1500525
No, you can't do that. But you can have a static Dictionary<Type, int>
and find out the type at execution time by calling GetType
.
class Base
{
private static readonly IDictionary<Type, int> instanceCounterMap
= new Dictionary<Type, int>();
protected int _id;
protected Base()
{
// I don't normally like locking on other objects, but I trust
// Dictionary not to lock on itself
lock (instanceCounterMap)
{
// Ignore the return value - we'll get 0 if it's not already there
instanceCounterMap.TryGetValue(GetType(), out _id);
instanceCounterMap[GetType()] = _id + 1;
}
}
}
Upvotes: 6
Reputation: 19765
I would suggest that rather than trying to get a class to count instances of itself you create a factory class that manages the lifetimes of the instances. Rather than newing a 'OtherDerived' you implement a OtherDerivedFactory with a Build or Create method to serve them up. Internally, it can count instances.
Heck, abstract it a bit more with an interface and then you can inject the factory at run-time. Great for testing, alternate implementations, etc.
Upvotes: 0