令人困惑的重载决议

时间:2015-08-14 02:28:11

标签: c# overload-resolution

我有一个继承自另一个类的类,允许使用可空值。但是当我使用非可空值时,它无论如何都会使用重载为空。

我不明白为什么类c2的功能在这段代码中掩盖了类c1的功能:

class c1
{
    public void fn1(int value)
    {
        Console.WriteLine("value {0} is normal", value);
    }
    public void fn1(int? value)
    {
        Console.WriteLine("value {0} is nullable", value);
    }
    public void fn2(int value)
    {
        Console.WriteLine("value {0} is normal", value);
    }
}
class c2: c1
{
    public void fn2(int? value)
    {
        Console.WriteLine("value {0} is nullable", value);
    }
}

class Program
{
    static void Main(string[] args)
    {
        c1 o1 = new c1();
        c2 o2 = new c2();
        int val = 10;
        o1.fn1(val);
        o2.fn1(val);
        o2.fn2(val);
        Console.ReadLine();
    }
}

结果是:

value 10 is normal.
value 10 is normal.
value 10 is nullable.

然而,c2具有函数fn2(int)。

3 个答案:

答案 0 :(得分:2)

这是我在Jon Skeet博客上发现的。

  

继承可能会导致混乱的效果。当编译器去的时候   寻找实例方法重载,它考虑编译时   调用的“目标”的类,并查看声明的方法   那里。如果它找不到合适的东西,那么它会查看父级   上课......然后是祖父母班等。这意味着如果有的话   在层次结构的不同层次上的两种方法,“更深层次”   将被选中,即使它不是“更好的功能成员”   电话。

http://csharpindepth.com/Articles/General/Overloading.aspx

答案 1 :(得分:2)

在许多边缘情况下都是如此,没有神圣的“为什么”它,它只是如何编写C#规范。他们可以通过其他方式做到这一点,但决定这样做。 https://msdn.microsoft.com/en-us/library/aa691336(v=vs.71).aspx

最相关的部分(来自上面链接的C#规范的“7.4.2重载分辨率”,不同版本的规范在其他部分可能有相似的文字):

  

方法调用的候选集不包括...如果派生类中的任何方法适用,则基类中的方法不是候选

答案 2 :(得分:0)

就像说Handoko.Chen,在Jon Skeet的博客上我们可以找到

  

编译器会忽略子代中的重写方法。

所以我发现的唯一方法是隐藏继承方法:

class c2: c1 {
    public void fn2(int? value) {
        Console.WriteLine("value {0} is nullable", value);
    }
    public new void fn2(int value) {
        base.fn2(value);
    }
}