I'm not sure why (most) of the answers mention reflection - good ol' polymorphism works just fine for this. Getting the runtime type name is easy - it's just this.GetType().Name
.
The only somewhat tricky part is maintaining unique counters per class. That's been discussed before on SO - but I can't find a link ATM. But, the bottom line, is that you can either (ab)use generics or maintain a Dictionary<Type, int>
to keep track.
The generic version works because each different type parameter creates a different generic class - so they each have different static counters:
abstract class Command<T> where T : Command<T> {
private static int counter = 1;
private static object syncLock = new object();
protected Command() {
lock (syncLock) {
_name = this.GetType().Name + counter++.ToString();
}
}
public string Name { get { return _name; } }
private string _name;
}
class Blur : Command<Blur> { }
class Sharpen : Command<Sharpen> { }
There's no need to override anything in the derived classes, but you do have to make sure your inherited Command<T>
is correct - or you'll share counters. I also used a lock to synchronize access to counter - assuming you'll create instances from more than 1 thread.
If you don't like the generic version, then a Dictionary<Type, int>
works just as well.
abstract class Command {
private static Dictionary<Type, int> counter = new Dictionary<Type, int>();
private static object syncLock = new object();
protected Command() {
Type t = this.GetType();
lock (syncLock) {
if (!counter.ContainsKey(t)) {
counter.Add(t, 0);
}
_name = t.Name + counter[t]++.ToString();
}
}
public string Name { get { return _name; } }
private string _name;
}
class Blur : Command { }
class Sharpen : Command { }
Since you'll be creating "millions" of each, I'd probably profile both and check memory usage. I don't particularly care for the generic approach - since it's easy to screw up and pass the wrong type parameter - but I suspect it's memory usage is a bit better. Also, if you're going to create > int.MaxValue
, you'll have to worry about overflow.
All that being said, I'm not sure why you wouldn't just maintain an index addressable collection and reference them by index - like Blur[0]
?