如何在C#中重写子类的重写方法中的子类型?

我有一个带有over-ridden方法的子类,我知道它总是返回基类中声明的返回类型的特定子类型。 如果我以这种方式编写代码,它将无法编译。 由于这可能没有意义,让我举一个代码示例:

class BaseReturnType { } class DerivedReturnType : BaseReturnType { } abstract class BaseClass { public abstract BaseReturnType PolymorphicMethod(); } class DerivedClass : BaseClass { // Compile Error: return type must be 'BaseReturnType' to match // overridden member 'BaseClass.PolymorphicMethod()' public override DerivedReturnType PolymorphicMethod() { return new DerivedReturnType(); } } 

有没有办法在C#中实现这一目标? 如果没有,那么实现类似目标的最佳方法是什么? 为什么不允许这样做? 它似乎不允许任何逻辑不一致,因为从over-ridden方法返回的任何对象仍然is BaseReturnType 。 也许有些东西我没考虑过。 或者原因可能是技术或历史。

遗憾的是,C#中不支持协变返回类型以进行方法重写。 (Ditto逆变参数类型。)

如果您正在实现一个接口,您可以使用“弱”版本明确地实现它,并提供具有更强合同的公共版本。 为了简单地覆盖父类,你不会有这种奢侈我害怕:(

(编辑:Marc有一个合理的解决方案 – 虽然它非常丑陋,隐藏方法对于可读性来说通常是一件坏事。没有冒犯意味着,Marc;)

相信这实际上是一种CLR限制,而不仅仅是语言限制 – 但我可能错了。

(作为历史问题,Java(该语言)在1.5之前具有相同的限制 – 但它在generics的同时获得了协方差。)

如果不困扰你,你可以让这个类变得通用:

  class BaseReturnType { } class DerivedReturnType : BaseReturnType { } abstract class BaseClass where T : BaseReturnType { public abstract T PolymorphicMethod(); } class DerivedClass : BaseClass { // Error: return type must be 'BaseReturnType' to match // overridden member 'BaseClass.PolymorphicMethod()' public override DerivedReturnType PolymorphicMethod() { return new DerivedReturnType(); } } 

如果引入一个额外的方法来覆盖(因为你不能overridenew的同一类型的同名方法),你可以这样做:

 abstract class BaseClass { public BaseReturnType PolymorphicMethod() { return PolymorphicMethodCore();} protected abstract BaseReturnType PolymorphicMethodCore(); } class DerivedClass : BaseClass { protected override BaseReturnType PolymorphicMethodCore() { return PolymorphicMethod(); } public new DerivedReturnType PolymorphicMethod() { return new DerivedReturnType(); } } 

现在,您在每个级别都有一个具有正确类型的PolymorphicMethod方法。

generics不一定是要走的路。 特别是,(Derived)类型不被认为是(Base)类型。

首先,向派生类添加一个新方法,该方法将返回具有正确类型的值。 其次,将覆盖方法标记为不可覆盖,并将其委托给新方法。

而已。 你已经解决了问题。 子类将无法重新扩展类型,因为它们必须覆盖您的新方法。

如果代码不对,我道歉; 我习惯了VB.net。

 abstract class C1 { public abstract IEnumerable F1(); } class C2 : C1 { public sealed override IEnumerable F1() { Return F2(); } public overridable IList F2() { Return {1, 2, 3, 4}; } } 
 class BaseReturnType { } class DerivedReturnType : BaseReturnType { } abstract class BaseClass { public abstract BaseReturnType PolymorphicMethod(); } class DerivedClass : BaseClass { // Error: return type must be 'BaseReturnType' to match // overridden member 'BaseClass.PolymorphicMethod()' public override BaseReturnType PolymorphicMethod() { return new DerivedReturnType(); } } 

这应该工作

将Derived类上的方法签名更改为:

  public override BaseReturnType PolymorphicMethod() { return new DerivedReturnType(); } 

C#不支持变量返回类型。 你可以查看这篇文章,了解如何使用Generics … http://srtsolutions.com/blogs/billwagner/archive/2005/06/17/covaraint-return-types-in-c.aspx

以下是在模型中使用generics的示例:

 public class BaseReturnType { } public class DerivedReturnType : BaseReturnType { } public abstract class BaseClass where T : BaseReturnType { public abstract T PolymorphicMethod(); } public class DerviedClass : BaseClass { public override DerivedReturnType PolymorphicMethod() { throw new NotImplementedException(); } } 

在我看来,你需要返回一个接口,而不是一个基类。