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

时间:2013-01-07 18:14:20

标签: c# polymorphism virtual method-overriding

我想在抽象类中使用确切名称初始化虚拟方法。

在类中,这是继承器覆盖方法,我可以覆盖:

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

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

abstract class A
{
    public virtual void Func1() { }
}

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

我知道,C#需要在基类中使用返回类型/ args,但在这种情况下可能会有一些关键字new的提示吗?

5 个答案:

答案 0 :(得分:3)

您只能override确切的名称和参数。您可以new无论您想要什么,但这都不会覆盖 - 只是隐藏在完全匹配的情况下。

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

示例:

public abstract void Func1( MyArgumentsType input );

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

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

答案 1 :(得分:3)

你不能这样做。覆盖方法需要具有完全相同的签名,其中包括参数和返回类型。您无法告诉编译器使用不同的参数和返回类型覆盖方法。

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

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

答案 2 :(得分:3)

方法覆盖意味着修改继承成员的虚拟实现而不是签名。正如您所指出的,new关键字将隐藏基类的具有相同名称的成员实现。但是,它只是可选的,请看一下这个benefit of using new keyword in derived class member having same name with base class member

答案 3 :(得分:3)

您希望实现类似于ToString方法的行为,该方法针对不同类型(例如.ToString()float.ToString("c"))具有许多不同的风格。

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

请注意,在函数解析时考虑的C#结果类型更新,因此您不能真正拥有2个具有相同名称和相同参数的函数,并且期望“正确”选择一个函数。如果两者同时可见,则会出现编译时错误。方法前面的new关键字只对该类(和派生的)可见该方法,并使用相同的签名隐藏基类方法。不幸的是,当使用包含派生类的基类的变量来调用这个方法时,这样做几乎可以保证很多混乱 - 尽管所有努力都要隐藏它,但是会调用基类中的虚拟方法。

答案 4 :(得分:1)

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

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

覆盖背后的想法是你在super / base上调用一个方法,然后它解析为重写的实现。按照这种逻辑,您应该能够bar致电a.Func1(),并且应该调用B中的方法:

a.Func1(???)

但由于缺少参数,这里不可能。

存在参数逆变和返回类型协方差的概念; here在SO中是一个有趣的答案,链接到Eric Lippert的帖子应该是一个有趣的读物。