关于c#:奇怪的重复模板模式与其他泛型类型

Curiously recurring template patterns with additional generic types

比如说,我想要一个通用的Box类,它可以包含一些内部内容,所以它是Box类。Box有一个Transform方法,该方法返回Box

1
public Box<U> Transform<U>(Func<T, U> transform)

到目前为止,这很简单。但是,我实际上需要一个抽象的Box,因为值的装箱和转换方式是特定于实现的。(我不能有接口,因为有其他方法是通过抽象方法的组合来实现的,但这无论如何都不会改变任何东西)。

当然,我希望重写的Transform方法返回Box的适当子类,而不是Box本身。由于重写方法的返回类型在C中是不变的,所以我使用奇怪的循环模板模式(参见IComparable)。

1
public abstract class Box<B, T> where B : Box<B, T>

现在,我从以东所继承的每一个阶级(10)都应该指代它自己,否则所有的地狱都会散去:

1
public class FooBox<T> : Box<FooBox, T>

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

1
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'. There is no implicit reference conversion from 'B' to 'Test.Box'. (CS0311)编译。这是有道理的,因为返回类型现在是Box,而b是Box,而不是Box

直截了当的解决方案不起作用:

1
public abstract Box<B, U> Transform<U>(Func<T, U> transform) where B : Box<B, U>;

无法用'Test.Box.Transform()' does not define type parameter 'B' (CS0699)编译。

有没有办法解决这个问题,或者我真的把自己画成了一个角落?


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

1
public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform) where B2 : Box<B2, U>;

更新:您声明:

now I cannot guarantee that B2 and B are actually the same derived class, which was my goal

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

例如:

1
2
3
public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform)
    where B2 : Box<B2, U>
    where U : T