c#虚方法覆盖返回类型&方法参数

本文关键字:方法 参数 返回类型 覆盖 | 更新日期: 2023-09-27 17:50:52

我想在抽象类中初始化具有确切名称的虚拟方法。

在class中,这是一个继承重写方法这样,我可以重写:

  • 基方法返回类型
  • 方法的参数

为了告诉你,我真正想做的是这样的:

abstract class A
{
    public virtual void Func1() { }
}
class B : A
{
    override string Func1(int a, int b)
    {
         return (a + b).ToString();
    }
}

我知道,c#需要使用返回类型/args作为基类,但也许有一些提示关键字new在这种情况下?

c#虚方法覆盖返回类型&方法参数

您只能override确切的名称和参数。你可以new任何你想要的,但这不是覆盖-只是隐藏在一个完全匹配的情况下。

我想在你的情况下,你要么想为所有可能的组合创建重载,要么创建一个基本的抽象方法,它接受一个可以包含你想要的参数的单一类型。

的例子:

public abstract void Func1( MyArgumentsType input );

现在派生类被强制覆盖一个方法,但你可以传递一组健壮的参数给方法,可以处理更多的场景。

多态性在这里对您有利,因为您可以将派生的参数类型传递给具有特定情况属性的方法。当然,这需要实现方法理解更派生的参数类型。

方法重写意味着修改继承成员的虚实现,而不是修改其签名。正如您所指出的,new关键字将隐藏同名成员的基类实现。然而,这只是可选的,看看在与基类成员同名的派生类成员

中使用new关键字的
好处

看起来您想要实现类似于ToString方法的行为,对于不同类型(如.ToString()float.ToString("c"))有许多不同的风格。

在这种情况下,ToString的不同实现不是Object.ToString的实现,而是基于参数适当解析的派生对象上的普通附加方法。所有的派生类最终都有一个虚拟的ToString方法(来自基类并可能在当前类中实现)和其他可选的类似命名的非虚拟方法。

请注意,在c#中,结果类型更新考虑了函数解析时间,所以你不可能真正有两个具有相同名称和相同参数的函数,并期望其中一个被"正确"选择。如果两者同时可见,则会得到编译时错误。方法前面的new关键字使得只有该方法对该类(和派生类)可见,并隐藏具有相同签名的基类方法。不幸的是,这样做几乎保证了很多混乱,当一个人使用基类的变量持有派生类调用这个方法-从基类的虚的一个将被调用,尽管所有的努力隐藏一个。

你不能这么做。重写方法需要具有完全相同的签名,其中包括参数和返回类型。你没有办法告诉编译器用不同的参数和返回类型覆盖一个方法。

如果你想要多态行为,你需要有兼容的签名。否则,编译器不能保证将以多态方式找到所需的方法。

没有可靠的方法将签名void Func1()string Func1(int a, int b)视为多态的。您可以使用内部传递lambda的out参数泛化它们,但无论如何-要利用多态行为,您需要将它们带到一个公共签名中。

想想看…它将如何运作?假设您有一个引用,其静态类型是A,但动态类型是B,如下所示:

foo(B b) { bar(b); }
bar(A a) { 
}

重写背后的思想是,你在super/base上调用一个方法,它会解析到被重写的实现。根据这个逻辑,你应该能够在bar中调用a.Func1(),它应该调用B中的方法:

a.Func1(???)

但是这里不可能,因为缺少参数

有参数逆变和返回类型协方差的概念;这里有一个有趣的答案,链接到Eric Lippert的一篇文章,应该是一个有趣的阅读。