Let's say I want to have a generic Box class that can contain something inside, so it's Box<T> . Box<T> has a Transform method that returns Box<U> :
public Box<U> Transform<U>(Func<T, U> transform)
So far it has been pretty simple. However, I really need an abstract Box , since the way to insert and convert values ββis implementation dependent. (I cannot have an interface, since there are other methods that are implemented using the composition of abstract methods, but this does not change anything).
Of course, I want my overridden Transform methods to return the corresponding subclass of Box , not Box . Since the return types of overriding methods are invariant in C #, I turn to a curiously repeating template pattern (see IComparable<T> ):
public abstract class Box<B, T> where B : Box<B, T>
Now, every class that I inherit from Box<B, T> must refer to itself or the whole hell breaks:
public class FooBox<T> : Box<FooBox, T>
However, this completely destroys the Transform method:
public abstract Box<B, U> Transform<U>(Func<T, U> transform);
The type 'B' cannot be used as type parameter 'B' in the generic type or method 'Test.Box<B,T>'. There is no implicit reference conversion from 'B' to 'Test.Box<B,U>'. (CS0311) The type 'B' cannot be used as type parameter 'B' in the generic type or method 'Test.Box<B,T>'. There is no implicit reference conversion from 'B' to 'Test.Box<B,U>'. (CS0311) The type 'B' cannot be used as type parameter 'B' in the generic type or method 'Test.Box<B,T>'. There is no implicit reference conversion from 'B' to 'Test.Box<B,U>'. (CS0311) . This makes sense since the return type is now Box<B, U> , and B is Box<B, T> , which is not Box<B, U> .
A simple fix will not work:
public abstract Box<B, U> Transform<U>(Func<T, U> transform) where B : Box<B, U>;
cannot compile with 'Test.Box<B,T>.Transform<U>()' does not define type parameter 'B' (CS0699) .
Is there any way to resolve this, or have I really painted myself in a corner?