问题描述
|
问题的最明显的例子是函数Clone(只是一个EXAMPLE伙计们)。假设您有BaseClass和DerivedClass -除非我错过了什么,否则在两个函数(每个类分别克隆)中,您分别创建了BaseClass和DerivedClass,但实际上返回了对象。
如果要使用\“ real \”类,这就是问题。
到目前为止,我仅看到两种解决此问题的方法:
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最喜欢的\“因为每个功能都需要... \” ;-)我认为允许覆盖一个不存在技术性(逻辑性等)问题结果类型已更改的函数如果替代函数结果是从原始函数结果类型派生的。
例:
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 \”不在主题上。谢谢。
解决方法
检查以下两个问题:
为什么没有ICloneable ?
C#:覆盖返回类型
基本上,处理此问题的方法是定义具有适当返回类型的通用接口,例如
和ICloneable 是两回事。
“仅在返回类型上具有不同的功能”在技术上是“可能的”,实际上CLR允许这样做,但C#不允许这样做,这可能是因为不可能猜测总是正确的重载。 (实际上,使用C#,您可以使用隐式强制转换运算符:将它们编译为名称为op_Implicit且返回类型不同的函数)。
interface ICloneable<T> {
T Clone();
}
但是,这不允许您将接口用作基本类型,因为ICloneable