2012-03-27 52 views
3

在给出的示例中(对于代码样式感到遗憾,它符合紧凑自包含的repro的兴趣),所调用的方法始终是B中的虚方法有额外的整数参数,但我期望在C中实现的方法是一个被调用的方法。C#为可选参数和多级继承选择一种不同的方法

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace MethodChoosing 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      C c = new C(); 
      c.M(); 

      Console.ReadKey(); 
     } 
    } 

    public class A 
    { 
     public virtual void M(bool? a = null) 
     { 
      Console.WriteLine("base base"); 
     } 
    } 

    public class B : A 
    { 
     public override void M(bool? a = null) 
     { 
      Console.WriteLine("base override"); 
     } 

     public virtual void M(bool? a = null, int? b = null) 
     { 
      Console.Write("base new"); 
     } 
    } 

    public class C : B 
    { 
     public override void M(bool? a = null) 
     { 
      Console.WriteLine("pick me!"); 
     } 
    } 
} 

,输出 “新基础”。这显然不是我所期望的行为,是否有人能够解释推理?

编辑: 改变主,使c.M有一个true或null参数仍然选择不正确的方法。

+0

退房这个问题: http://stackoverflow.com/questions/8909811/c-sharp-optional-parameters-on-overridden-methods它可能不是同样的事情,但它接近。 – 2012-03-27 13:45:20

+0

你已经结合了重载和可选参数。你永远不应该那样做。对于你的犯罪,我判你阅读[Eric Lippert关于可选参数角落案件的四部分系列](http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases -part-one.aspx)加上这个[“如果它伤害,那么不要这样做”prequel](http://blogs.msdn.com/b/ericlippert/archive/2011/02/10/optional-arguments - 酮两种-ends.aspx)。 – 2012-03-27 13:46:55

+0

我从来不会这样做,这是一个随机的想法,变成了一些调查:) – 2012-03-27 16:00:47

回答

4

该规范的第7.4节指出,在成员查找过程中正在考虑的可访问方法集中排除了覆盖方法。考虑到原始问题中的方法,类A有一个未覆盖的方法,类B有一个未覆盖的方法,而类C没有。从该集合中的两个方法中,编译器在大多数派生类中选择匹配方法(在这种情况下,类B是“基本新”函数)。

如果B类中的匹配函数不存在,那么最好的函数匹配就是A类中的虚函数。在这种情况下,该对象的运行时类型将用于选择哪一个在A,B或C类中的重写函数将被选择。作为问题的陈述,因为该方法被称为C类的对象,将是“接我!”功能。

1

对于c.M(),假定调用M(null, null)。 这是可选参数如何工作的方式。 如果您要拨打C.M,请致电C.M(null)或在C类中覆盖M(bool? a = null, int? b = null)

+0

如果你打电话C.M(真)它仍然会从B类选择虚拟。 – 2012-03-27 14:50:19

1

这就是所谓的不明确的调用。由于您有两个方法仅由一个可选参数分隔,因此应用程序似乎选择了可满足大多数参数的方法。

编辑:@lazyberezovsky说,我在那里并不完全正确。如果您有一种方法可以满足NO参数,则优先

+0

啊,是的,我刚刚匹配C中的参数数量,然后打印出“接我!”。 – 2012-03-27 14:13:52

+0

将参数传递给C.M,既是true也是null,它仍然选择相同的方法。这似乎很奇怪,因为我明确提供了足够的参数来完成采用一个参数的方法,但它仍然选择具有最多可选参数的参数。 – 2012-03-27 14:52:16

+0

是的,因为您仍然匹配具有最多参数的方法。可选参数的乐趣:D。 – mattytommo 2012-03-27 14:59:28