最明显的问题是Clone功能(只有示例人)。假设你有BaseClass和DerivedClass - 除非我错过了两个函数(每个类的克隆),你分别创建了BaseClass和DerivedClass,但实际上你返回了对象。 如果你想使用“真正的”类,这就是问题。
到目前为止,我只看到了这个问题的两种解决方法:
1。每次将函数的结果强制转换为适当的类
var real_stuff = (RealStuff)x.Clone(); // I want real stuff
2。提供第二个功能,因此您将拥有Clone(如果您在基类级别工作)和CloneThis(如果您想在给定的类中工作,那么结果将从一个类更改为类电平)
public override object Clone()
{
return CloneThis();
}
public RealStuff CloneThis()
{
return new RealStuff(this);
}
第一个是丑陋的,第二个是令人厌倦的。
问题:您如何处理此问题?
另一件事 - 如果您愿意,请对此进行评论 - 这是为什么当覆盖函数签名检查如此严格时?除了“因为它是按照这种方式设计”或Eric Lippert最喜欢的“因为每个功能都需要......”;-)我看到没有技术(和逻辑等)的问题,允许覆盖更改结果类型的函数 IF 覆盖函数结果是从原始函数结果类型派生的。
示例:
class ClassA
{
public virtual ClassA GetIt() ...
}
class ClassB : ClassA
{
public override ClassB GetIt() ...
}
目前它不是正确的代码,但我认为它在技术上可能是,因为ClassB派生自ClassA。无论你对输出做什么,“接收器”都需要ClassA,所以ClassB满足了这个要求。
所以你可以写:
ClassA class_a_b = new ClassB();
ClassB class_b_b = new ClassB();
ClassA result1 = class_b_b.GetIt();
ClassA result2 = class_a_b.GetIt();
ClassB result3 = class_b_b.GetIt();
// incorrect, derived GetIt would be called OK,
// but the signature is taken from ClassA
ClassB result4 = class_a_b.GetIt();
我也不认为有这样的能力,任何人都会对这种行为感到惊讶,恕我直言,这是一致的。
请保留您的答案主题,“您不应该使用ICloneable” NOT 主题。谢谢。
答案 0 :(得分:3)
检查这两个问题:
基本上,处理此问题的方法是定义具有适当返回类型的通用接口,例如
interface ICloneable<T> {
T Clone();
}
但是,这不允许您将接口用作基本类型,因为ICloneable&lt; ClassOne&gt;和ICloneable&lt; ClassTwo&gt;是两回事。
只有返回类型才能使函数“技术上可行”,事实上CLR允许这样做,但C#不会,可能因为总是无法猜出调用的正确重载。 (实际上使用C#,您可以使用隐式转换运算符执行此操作:将它们编译为名称为op_Implicit且返回类型不同的函数。)