奇怪的重复模板模式与其他泛型类型

Ale*_*xey 6 c# generics crtp

假设我想要一个Box可以包含内部内容的泛型类,所以它是一个Box<T>.Box<T>有一个Transform方法返回一个Box<U>:

public Box<U> Transform<U>(Func<T, U> transform)
Run Code Online (Sandbox Code Playgroud)

到目前为止,这很简单.但是,我实际上需要一个摘要Box,因为值被加框和转换的方式是特定于实现的.(我没有接口,因为有其他方法是通过抽象方法的组合实现的,但这并不会改变任何东西).

当然,我希望我的重写Transform方法返回一个合适的子类Box,而不是Box它自己.由于覆盖方法的返回类型在C#中是不变的,我转向奇怪的重复模板模式(请参阅参考资料IComparable<T>):

public abstract class Box<B, T> where B : Box<B, T>
Run Code Online (Sandbox Code Playgroud)

现在我继承的每一个课都Box<B, T>应该引用自己或者所有地狱都是松散的:

public class FooBox<T> : Box<FooBox, T>
Run Code Online (Sandbox Code Playgroud)

但是,这完全破坏了这个Transform方法:

public abstract Box<B, U> Transform<U>(Func<T, U> transform);
Run Code Online (Sandbox Code Playgroud)

无法编译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).这是有道理的,因为返回类型现在Box<B, U>是B Box<B, T>而不是Box<B, U>.

直截了当的修复不起作用:

public abstract Box<B, U> Transform<U>(Func<T, U> transform) where B : Box<B, U>;
Run Code Online (Sandbox Code Playgroud)

无法编译'Test.Box<B,T>.Transform<U>()' does not define type parameter 'B' (CS0699).

有什么方法可以解决这个问题,还是我真的把自己画成了一个角落?

Jon*_*ton 1

我认为直接修复的问题是B类型参数的重用。尝试其他方法,并将其作为类型参数包含在内:

public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform) where B2 : Box<B2, U>;
Run Code Online (Sandbox Code Playgroud)

更新:您说:

现在我不能保证 B2 和 B 实际上是相同的派生类,这是我的目标

但事实并非如此,B2不(不能?)继承自B,如果您愿意,U可以继承。T您可以将其作为约束。但这对于模式来说并不是绝对必要的,因为它取决于主体来Transform解决它。

例如:

public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform) 
    where B2 : Box<B2, U>
    where U : T
Run Code Online (Sandbox Code Playgroud)