你如何处理不同类型结果的覆盖函数?

时间:2011-05-26 06:53:19

标签: c# polymorphism override

最明显的问题是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 主题。谢谢。

1 个答案:

答案 0 :(得分:3)

检查这两个问题:

基本上,处理此问题的方法是定义具有适当返回类型的通用接口,例如

interface ICloneable<T> {
    T Clone();
}

但是,这不允许您将接口用作基本类型,因为ICloneable&lt; ClassOne&gt;和ICloneable&lt; ClassTwo&gt;是两回事。

只有返回类型才能使函数“技术上可行”,事实上CLR允许这样做,但C#不会,可能因为总是无法猜出调用的正确重载。 (实际上使用C#,您可以使用隐式转换运算符执行此操作:将它们编译为名称为op_Implicit且返回类型不同的函数。)