问题
During some research, I ran into an inheritance pattern using generics I have not seen before.
http://thwadi.blogspot.ca/2013/07/using-protobuff-net-with-inheritance.html
public abstract class BaseClass<TClass> where TClass : BaseClass<TClass>
{
//...
}
public class DerivedClass : BaseClass<DerivedClass>
{
//...
}
Usage:
static void Main(string[] args)
{
DerivedClass derivedReference = new DerivedClass();
//this looks odd...
BaseClass<DerivedClass> baseReference = derivedReference;
//this doesn't work
//BaseClass baseClass = derivedReference;
}
I was surprised that this even worked, I had to test it myself. I still can't understand why you would want to do this.
The only thing I could come up with, is preventing different derived classes from being stored in a collection together as their base class. This may be the reason, I guess I'm just curious to the application.
回答1:
It is called the Curiously recurring template pattern it is often used to allow methods in the class to use the type of the derived class as a passed in or returned parameter.
For example, this is Clone method implemented so that only each layer needs to add it's own properties to the method as it goes down the chain.
public abstract class BaseClass<TClass> where TClass : BaseClass<TClass>, new()
{
public int Foo {get;set;}
public virtual TClass Clone()
{
var clone = new TClass();
clone.Foo = this.Foo;
return clone;
}
}
public class DerivedClass : BaseClass<DerivedClass>
{
public int Bar {get;set;}
public override DerivedClass Clone()
{
var clone = base.Clone();
clone.Bar = this.Bar;
return clone;
}
}
Usage:
static void Main(string[] args)
{
DerivedClass derivedReference = new DerivedClass();
DerivedClass clone = derivedReference.Clone();
}
回答2:
As an example of usage, suppose you want to implement some chainable builder methods on the base type and derived type like this:
var d = new DerivedClass();
d.SetPropertyA("some value").SetPropertyB(1);
While SetPropertyA belongs to base class and SetPropertyB belongs to derived class.
By implementing classes like below, when chaining methods, after calling SetPropertyA because the return value is of type DerivedClass you can call SetPropertyB:
public abstract class BaseClass<TClass> where TClass : BaseClass<TClass>
{
public string A {get ; set; }
public TClass SetPropertyA(string value)
{
this.A=value;
return this as TClass;
}
}
public class DerivedClass : BaseClass<DerivedClass>
{
public int B {get ; set; }
public DerivedClass SetPropertyB(int value)
{
this.B=value;
return this;
}
}
Then if you have some other derived classes, each of them can use the base SetPropertyA knowing the return value is of type of itself.
来源:https://stackoverflow.com/questions/34213055/odd-generic-inheritance-pattern