Is it advisable to use self-referencing generic inheritance?
public abstract class Entity<T> {
public Guid Id {get; set;}
public int Version {get; set;}
public T Clone() {
...
// clone routine
...
return T;
}
}
public class Customer : Entity<Customer> {
public string CustomerName {get; set;}
...
}
How does one cast Customer to the base Entity class? What advantage does "Customer : Entity" provide? I see this kind of inheritance in examples showing NHibernate domain modeling.
Is it better to use "Customer : Entity" without the generics?
You should use it when you need it, not just because you can. In the example above, it makes some sense to implement Clone()
. However, as you rightly point out, it means that your entity classes won't actually have a common base class, and properties that are truly common to them won't be accessible. The correct way to handle this is to split it in generic and non-generic parts:
public abstract class Entity {
public Guid Id {get; set;}
public int Version {get; set;}
}
public abstract class Entity<T> : Entity where T : Entity<T> {
public T Clone() {
...
// clone routine
...
return T;
}
}
Also, note the where
part that I've added to declaration of Entity<T>
- it ensures that this class can only be used as a part of this recursive pattern.
In the company i work for, the project I work on uses heavily this kind of trick. In fact, it is even promoted as a pattern in the code. Thus i can speak from experience: don't use it.
They may be cases where the self-referencing implementation is far simpler, more efficient and easier to read, but I have never encountered such a case. Heavy use of it makes code maintenance a nightmare, and in most cases can be avoided with only a normal inheritance and a casting of your method result if needed. And the performance cost of a casting into the derived class is negligible compared to the maintenance cost of your code.
So if you find the rare example where it is advisable to use self-referencing generic inheritance, go ahead and do so. But think twice beforehand, as there is probably a better way to do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With