views:

200

answers:

2

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?

+2  A: 

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.

Pavel Minaev
Are there any other advantage to using the generic entity? I could make the Clone method a generic method if there are no other advantages.
Mank
How would you make `Clone` generic?
Pavel Minaev
I could do public T Clone<T>() { serialize/deserialize T, return T}
Mank
But then it means that if you have entity classes `Foo` and `Bar`, you can call `bar.Clone<Foo>()`. And what is that supposed to do?
Pavel Minaev
Maybe I can create a static clone class on Entity. My question is if self-referencing has any other advantages besides the clone example.
Mank
A: 

Thanks for the idea of splitting a self-referencing generic class up into a self-referencing and and a non-self-referencing part. That solved a problem I had in how to pass a reference to the object to another class in another assembly - it was not possible to pass the self-referencing object.

RenniePet
Oops, this was supposed to be a comment to Pavel Minaev, not an answer to the original poster.
RenniePet