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

如何在C#中的子类的重写方法中返回子类型?,c#,inheritance,C#,Inheritance,我有一个子类,它有一个过度使用的方法,我知道它总是返回基类中声明的返回类型的特定子类型。如果我这样写代码,它将无法编译。因为这可能没有意义,让我举一个代码示例: class BaseReturnType { } class DerivedReturnType : BaseReturnType { } abstract class BaseClass { public abstract BaseReturnType PolymorphicMethod(); } class Derive

我有一个子类,它有一个过度使用的方法,我知道它总是返回基类中声明的返回类型的特定子类型。如果我这样写代码,它将无法编译。因为这可能没有意义,让我举一个代码示例:

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#来实现这一点?如果不是,实现类似目标的最佳方式是什么?为什么不允许呢?它似乎不允许任何逻辑不一致,因为从过度使用的方法返回的任何对象仍然
是BaseReturnType
。也许有些事情我没有考虑过。或者原因可能是技术或历史原因。

不幸的是,C#中不支持协变返回类型来进行方法重写。(与逆变参数类型相同。)

如果您正在实现一个接口,您可以使用“弱”版本显式地实现它,还可以提供一个具有更强契约的公共版本。对于父类的简单重写,恐怕您没有这样的特权:(

(编辑:Marc有一个-虽然它很难看,而且方法隐藏通常对可读性是一件坏事。没有冒犯的意思,Marc;)

我相信这实际上是一个CLR限制,不仅仅是语言限制——但我很可能是错的


(历史上,Java(该语言)在1.5之前有相同的限制,但它与泛型同时获得协变。)

不幸的是,C中不支持协变返回类型用于方法重写(与逆变参数类型相同)

如果您正在实现一个接口,那么您可以使用“弱”版本显式地实现它,还可以提供具有更强契约的公共版本

(编辑:Marc有一个-虽然它很难看,而且方法隐藏通常对可读性是一件坏事。没有冒犯的意思,Marc;)

我相信这实际上是一个CLR限制,不仅仅是语言限制——但我很可能是错的


(历史上,Java(语言)在1.5之前有相同的限制,但它与泛型同时获得协方差。)

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

在我看来,您需要返回接口,而不是基类

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(); 
    }
}
这应该行得通


这应该可以

如果引入一个额外的方法来覆盖,您可以这样做(因为您不能
覆盖
新建
相同类型中具有相同名称的方法):


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

如果引入一个额外的方法来覆盖,您可以这样做(因为您不能
覆盖
新的
相同类型中具有相同名称的方法):


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

如果您不介意的话,您可以将类设置为泛型:

    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();
        }
    }
class BaseReturnType{}
类DerivedReturnType:BaseReturnType{}
抽象类基类,其中T:BaseReturnType
{
公共摘要T多态方法();
}
类派生类:基类
{
//错误:返回类型必须为“BaseReturnType”才能匹配
//重写的成员“BaseClass.PolymorphicMethod()”
公共重写DerivedReturnType多态方法()
{
返回新的DerivedReturnType();
}
}

如果您不介意的话,可以将类设置为泛型:

    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();
        }
    }
class BaseReturnType{}
类DerivedReturnType:BaseReturnType{}
抽象类基类,其中T:BaseReturnType
{
公共摘要T多态方法();
}
类派生类:基类
{
//错误:返回类型必须为“BaseReturnType”才能匹配
//重写的成员“BaseClass.PolymorphicMethod()”
公共重写DerivedReturnType多态方法()
{
返回新的DerivedReturnType();
}
}

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

 public override BaseReturnType PolymorphicMethod() 
 {
    return new DerivedReturnType();     
 }
C#不支持变量返回类型。您可以查看这篇文章,了解使用泛型实现这一点的方法

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

public class BaseReturnType
{
}
public class DerivedReturnType : BaseReturnType
{
}

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

}

public class DerviedClass : BaseClass<DerivedReturnType>
{
    public override DerivedReturnType PolymorphicMethod()
    {
        throw new NotImplementedException();
    }
}
公共类BaseReturnType
{
}
公共类DerivedReturnType:BaseReturnType
{
}
公共抽象类基类,其中T:BaseReturnType
{
公共摘要T多态方法();
}
公共类DerviedClass:基类
{
公共重写DerivedReturnType多态方法()
{
抛出新的NotImplementedException();
}
}

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

 public override BaseReturnType PolymorphicMethod() 
 {
    return new DerivedReturnType();     
 }
C#不支持变量返回类型。您可以查看这篇文章,了解使用泛型实现这一点的方法

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

public class BaseReturnType
{
}
public class DerivedReturnType : BaseReturnType
{
}

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

}

public class DerviedClass : BaseClass<DerivedReturnType>
{
    public override DerivedReturnType PolymorphicMethod()
    {
        throw new NotImplementedException();
    }
}
公共类BaseReturnType
{
}
公共类DerivedReturnType:BaseReturnType
{
}
公共抽象类基类,其中T:BaseReturnType
{
公共摘要T多态方法();
}
公共类DerviedClass:基类
{
公共重写DerivedReturnType多态方法()
{
抛出新的NotImplementedException();
}
}

泛型不一定是要走的路。特别是,(派生的)类型不被认为是(基的)类型

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

就这样。您已经解决了问题。子类将无法重新扩展该类型,因为它们必须重写您的新方法

如果代码不太正确,我深表歉意;我已经习惯了VB.net

abstract class C1 {
    public abstract IEnumerable<Byte> F1();
}
class C2 : C1 {
    public sealed override IEnumerable<Byte> F1() {
        Return F2();
    }
    public overridable IList<Byte> F2() {
        Return {1, 2, 3, 4};
    }
}
抽象类C1{
公共抽象IEnumerable F1();
}
C2类:C1类{
公共密封覆盖IEnumerable F1(){
返回F2();
}
P