Every so often I am making a simple interface more complicated by adding a self-referencing ("reflexive") type parameter constraint to it. For example, I might turn this:
interface ICloneable
{
ICloneable Clone();
}
class Sheep : ICloneable
{
ICloneable Clone() { … }
} //^^^^^^^^^^
Sheep dolly = new Sheep().Clone() as Sheep;
//^^^^^^^^
into:
interface ICloneable<TImpl> where TImpl : ICloneable<TImpl>
{
TImpl Clone();
}
class Sheep : ICloneable<Sheep>
{
Sheep Clone() { … }
} //^^^^^
Sheep dolly = new Sheep().Clone();
Main advantage: An implementing type (such as Sheep
) can now refer to itself instead of its base type, reducing the need for type-casting (as demonstrated by the last line of code).
While this is very nice, I've also noticed that these type parameter constraints are not intuitive and have the tendency to become really difficult to comprehend in more complex scenarios.*)
Question: Does anyone know of another C# code pattern that achieves the same effect or something similar, but in an easier-to-grasp fashion?
*) This code pattern can be unintuitive and hard to understand e.g. in these ways:
The declaration X<T> where T : X<T>
appears to be recursive, and one might wonder why the compiler doesn't get stuck in an infinite loop, reasoning, "If T
is an X<T>
, then X<T>
is really an X<X<…<T>…>>
." (But constraints obviously don't get resolved like that.)
For implementers, it might not be obvious what type should be specified in place of TImpl
. (The constraint will eventually take care of that.)
Once you add more type parameters and subtyping relationships between various generic interfaces to the mix, things get unmanageable fairly quickly.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…