我想说我想要一个可以包含内容的通用Box
类,所以它是Box<T>
。 Box<T>
使用Transform
方法返回Box<U>
:
public Box<U> Transform<U>(Func<T, U> transform)
到目前为止,这很简单。但是,我实际上需要一个抽象Box
,因为值被装箱和转换的方式是特定于实现的。 (我不能有一个接口,因为有其他方法是通过抽象方法的组合实现的,但这并不会改变任何东西)。
当然,我希望我的重写Transform
方法返回Box
的适当子类,而不是Box
本身。由于覆盖方法的返回类型在C#中是不变的,因此我转向curiously recurring template pattern(请参阅IComparable<T>
):
public abstract class Box<B, T> where B : Box<B, T>
现在,我从Box<B, T>
继承的每个班级都应该引用自己,或者所有地狱都松散了:
public class FooBox<T> : Box<FooBox, T>
然而,这完全破坏了Transform
方法:
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)
进行编译。这是有道理的,因为返回类型现在是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>;
无法使用'Test.Box<B,T>.Transform<U>()' does not define type parameter 'B' (CS0699)
进行编译。
有什么方法可以解决这个问题,还是我真的把自己画成了角落?
答案 0 :(得分:1)
我认为直接修复的问题是重用B
类型参数。尝试其他方法,并将其作为类型参数包含在内:
public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform) where B2 : Box<B2, U>;
更新:您说:
现在我不能保证B2和B实际上是相同的派生类,这是我的目标
但情况并非如此,B2
不会(不能?)从B
继承,如果您愿意,U
可能会继承T
。您可以将其包含在约束中。然而,对于模式来说,这并不是绝对必要的,因为它取决于Transform
的主体来进行排序。
e.g:
public abstract Box<B2, U> Transform<B2,U>(Func<T, U> transform)
where B2 : Box<B2, U>
where U : T