Reputation: 37391
I have an Animal
base class and every subclass needs a static string ID for identification purposes.
So I might have:
public class Dog : Animal {
public static readonly string ID = "dog";
}
I do this because I frequently need to use Dog.ID
throughout my app - in places where I don't yet have an instance.
However, I also need to access this when I have an instance, but I only want to put something like GetId()
in the base class:
public class Animal {
public string GetId() {
return ID;
}
}
The problem is, Animal
would not have access to the static ID field in the children.
Is there a way to do this that I've overlooked?
Upvotes: 1
Views: 400
Reputation: 1570
If you agree to an assumption that ID
equals to the type name, you can use this approach. It lets you define and inherit ID property in the base class.
Though I agree this might look quite strange at first sight.
public class Animal<T> where T : Animal<T>
{
public static readonly string ID = typeof(T).Name;
}
public class Dog : Animal<Dog>
{
}
public class Cat : Animal<Cat>
{
}
Expression Cat.ID
will return Cat
, and Dog.ID
will return Dog
.
Upvotes: 0
Reputation: 387
Implement explicit interface like this
public class Animal : IType
{
private static string _ID = "Animal";
string IType.ID
{
get
{
return getID();
}
}
public virtual string getID()
{
return _ID;
}
}
public class Dog : Animal, IType
{
public static readonly string _dogID = "dog";
string IType.ID
{
get
{
return _dogID;
}
}
public override string getID()
{
return _dogID;
}
}
....
// usage
Animal a = new Animal();
Animal d = new Dog();
Console.WriteLine(a.getID());
Console.WriteLine(d.getID());
Upvotes: 0
Reputation: 64943
If this is a static, set-once identifier, it seems like you should use an attribute instead of a static
field or property:
public class AnimalIdAttribute : Attribute
{
public AnimalIdAttribute(string id)
{
Id = id;
}
public string Id { get; }
}
public class Animal
{
public string Id => this.GetCustomAttribute<AnimalIdAttribute>(true)?.Id;
}
[AnimalId("dog")]
public class Dog : Animal
{
}
Also, if any animal should provide an Id
, your Animal
class should be an abstract
class which should also define an abstract Id
property:
public abstract class Animal
{
// Now you can access Id property implementation
// from Animal
public abstract string Id { get; }
}
public class Dog : Animal
{
public override string Id { get; } = "dog";
}
Upvotes: 1
Reputation:
What about an abstract method?
public class Dog : Animal
{
public static readonly string ID = "dog";
public override string GetId()
{
return ID;
}
}
public abstract class Animal
{
public abstract string GetId();
}
or virtual
public class Animal
{
public virtual string GetId()
{
return null;
}
}
Upvotes: 3
Reputation: 325
Or, you can do something like this:
public class Animal
{
public static string Id;
public virtual string GetId()
{
return Id;
}
}
public class Dog : Animal
{
public new static readonly string Id = "dog";
public override string GetId()
{
return Id;
}
}
This gives you ability to call Id from Class or an instance.
Upvotes: 0
Reputation: 18145
Ugly... But you could use reflection:
FieldInfo id = GetType().GetField("ID", BindingFlags.Public | BindingFlags.Static);
return id.GetValue(null);
Upvotes: 1