【问题标题】:Overload resolution of virtual methods虚方法的重载解析
【发布时间】:2011-10-11 00:18:21
【问题描述】:

考虑代码

public class Base
{
   public virtual int Add(int a,int b)
   {
      return a+b;
   }
}

public class Derived:Base
{
   public override int Add(int a,int b)
   {
      return a+b;
   }

   public int Add(float a,float b)
   {
      return (Int32)(a + b);
   }
}

如果我创建 Derived 类的实例并使用 int 类型的参数调用 Add 为什么它会使用 float 参数调用 Add 方法

Derived obj =new Derived()
obj.Add(3,5)

// why this is calling 
Add(float a,float b)

为什么不调用更具体的方法?

【问题讨论】:

  • 你怎么知道3和5是int?尝试指定它们的类型,看看会发生什么。
  • 你能编译这个吗?您可能会遇到一些转换错误,例如 float to int?
  • 这不会编译,因为没有从 float 到 int 的隐式转换。你确定第二个 Add 方法返回 int 吗?
  • @Ritch ,@Matthew ..即使你添加类似int a =3;int b=5;obj.Add(a,b);的内容也没有任何区别@
  • 另请阅读 John Skeet 的以下帖子。 http://csharpindepth.com/Articles/General/Overloading.aspx

标签: c# methods virtual overloading


【解决方案1】:

这是设计使然。 C# 语言规范第 7.5.3 节规定:

例如,方法调用的候选集不包括标记为覆盖的方法(第 7.4 节),如果派生类中的任何方法适用(第 7.6.5.1 节),则基类中的方法不是候选方法。

换句话说,因为您的Derived 类有一个未被覆盖的Add 方法,所以Base 类中的Add 方法(及其在Derived 中的覆盖版本)不再是重载的候选对象分辨率。

尽管Base.Add(int,int) 会更好匹配,但Derived.Add(float,float) 的存在意味着编译器甚至不会考虑基类方法。

Eric Lippert 在this blog post 中讨论了这种设计的一些原因。

【讨论】:

  • +1 好答案。证明、解释和进一步阅读的链接。
  • 有什么方法可以为虚拟方法添加重载,同时保持原始方法可见?
【解决方案2】:

http://www.yoda.arachsys.com/csharp/teasers-answers.html

选择重载时,如果派生类中声明了任何兼容的方法,则基类中声明的所有签名都将被忽略——即使它们在同一个派生类中被覆盖!

【讨论】:

    猜你喜欢
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多