想象一下,你有一个定义泛型值的泛型接口和这样的复制构造函数(替换ICloneable):
// T: type of value to hold, TU: type of the class itself
interface ICopyable<T,TU> where TU: ICopyable<T,TU> {
T Value { get; set; }
TU Copy();
}
这可以通过像这样的布尔值持有者来实现:
class BooleanHolder : ICopyable<Boolean, BooleanHolder> {
public BooleanHolder Copy() {
return new BooleanHolder(){ Value = Value };
}
}
现在问题是:你如何定义一个装有另一个ICopyable的装饰器类?我的工作想法不是:
class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> {
public DecoratingHolder<T,TU> Copy {
// won't compile as Value is of type T and not of type ICopyable<T,TU>
// as I expected - why is that?
return new DecoratingHolder<T,TU>(){ Value = Value.Copy };
}
}
请注意,我调用Copy
也复制了ICopyable<T,TU>
类型的值,这是为了确保深层复制。
那么我需要做些什么来改变这个结构呢?
答案 0 :(得分:3)
您可能只需要添加约束。您定义了ICopyable<T, TU> where TU : ICopyable<T, TU>
,但在DecoratingHolder
中,您从未在TU
上明确约束DecoratingHolder
。
更具体地说,我认为这就是这一部分:
class DecoratingHolder<T,TU> : ***ICopyable<ICopyable<T,TU>***
这导致了这个问题。您定义的是ICopyable<T,TU>
类型,但TU
未被限制为ICopyable<T, TU>
。 (一个人可能能够推断来自类声明/继承的其余部分,但编译器没有这个)一旦你添加了约束,那么编译器知道那个Value
是兼容的ICopyable<T,TU>
类型。
这对我编译很好(必须使用你提供的伪代码修复其他一些小问题):
class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>>
where TU : ICopyable<T,TU>
{
public ICopyable<T,TU> Value { get; set; }
public DecoratingHolder<T,TU> Copy() {
return new DecoratingHolder<T, TU>(){ Value = Value };
}
}
编辑:回想起来,你甚至需要ICopyable
的约束吗?似乎没有做太多,因为你已经一般地定义了传出类型。除非你在其他地方有代码,这取决于它因某种原因返回ICopyable<T, TU>
这一事实(无论如何它会返回一个强类型的TU
或BooleanHolder
或DecoratingHolder
)然后考虑倾销它。
interface ICopyable<T,TU>
{
T Value { get; set; }
TU Copy();
}
class BooleanHolder : ICopyable<Boolean, BooleanHolder>
{
public bool Value { get; set; }
public BooleanHolder Copy() {
return new BooleanHolder(){ Value = Value };
}
}
class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>>
{
public ICopyable<T,TU> Value { get; set; }
public DecoratingHolder<T,TU> Copy() {
return new DecoratingHolder<T, TU>(){ Value = Value };
}
}
编辑:从您的评论需要深层复制,然后保留约束(您将需要它们),并在Copy
上调用Value
(抱歉,我一定错过了这个细节)
class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>>
where TU : ICopyable<T,TU>
{
public ICopyable<T,TU> Value { get; set; }
public DecoratingHolder<T,TU> Copy() {
return new DecoratingHolder<T, TU>(){ Value = Value.Copy() };
}
}
任何给定类的Copy
方法都应该确保它们执行深层复制。 (我建议将Copy
重命名为DeepCopy
,如果您的框架需要它们是深层副本,并且您不希望实现意外地执行浅层操作)
答案 1 :(得分:0)
演员为我工作:
public DecoratingHolder<T, TU> Copy()
{
return new DecoratingHolder<T, TU>() { Value = (ICopyable<T, TU>)Value.Copy() };
}
我想在这种情况下,编译器并没有确定TU
和ICopyable<T, TU>
是一回事。