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

rec*_*ive 30 c# inheritance

我有一个带有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(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 19

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

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

(编辑:Marc有一个合理的解决方案 - 虽然它非常丑陋,隐藏方法通常对可读性不利.没有冒犯意味着,Marc;)

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

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


Sto*_*net 17

如果不困扰你,你可以使该类成为通用的:

    class BaseReturnType { }
    class DerivedReturnType : BaseReturnType { }

    abstract class BaseClass<T> where T : BaseReturnType
    {
        public abstract T PolymorphicMethod();
    }

    class DerivedClass : BaseClass<DerivedReturnType>
    {
        // Error: return type must be 'BaseReturnType' to match 
        // overridden member 'BaseClass.PolymorphicMethod()'
        public override DerivedReturnType PolymorphicMethod()
        {
            return new DerivedReturnType();
        }
    }
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 12

如果引入一个额外的方法来覆盖(因为你不能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(); }
}
Run Code Online (Sandbox Code Playgroud)

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