想象一下,您有一个定义通用值的通用接口和一个如下所示的复制构造函数(替换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>
类型的值,这是为了确保进行深拷贝。那么,为了使该结构正常工作,我必须进行哪些更改?
最佳答案
您可能只需要添加一个约束。您定义了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
,并且您不希望实现意外地进行浅化,则建议将其重命名为)