关于c#:派生类中的重载基方法

Overloading base method in derived class

因此,我正在玩C.*,以查看它是否与此帖子中的C++行为相匹配:HTTP://HbbSutTur.COM/2013/05/22/GOTW-5解决方案当我遇到这种奇怪的行为时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class BaseClass
{
    public virtual void Foo(int i)
    {
        Console.WriteLine("Called Foo(int):" + i);
    }

    public void Foo(string i)
    {
        Console.WriteLine("Called Foo(string):" + i);
    }
}

public class DerivedClass : BaseClass
{
    public void Foo(double i)
    {
        Console.WriteLine("Called Foo(double):" + i);
    }
}

public class OverriddenDerivedClass : BaseClass
{
    public override void Foo(int i)
    {
        base.Foo(i);
    }

    public void Foo(double i)
    {
        Console.WriteLine("Called Foo(double):" + i);
    }
}

class Program
{
    static void Main(string[] args)
    {
        DerivedClass derived = new DerivedClass();
        OverriddenDerivedClass overridedDerived = new OverriddenDerivedClass();

        int i = 1;
        double d = 2.0;
        string s ="hi";

        derived.Foo(i);
        derived.Foo(d);
        derived.Foo(s);

        overridedDerived.Foo(i);
        overridedDerived.Foo(d);
        overridedDerived.Foo(s);
    }
}

产量

1
2
3
4
5
6
Called Foo(double): 1
Called Foo(double): 2
Called Foo(string): hi
Called Foo(double): 1
Called Foo(double): 2
Called Foo(string): hi

显然,它倾向于隐式地将int转换为double,而不是基类中更具体的foo(int)。或者它是否将foo(int)隐藏在基类中?但是:为什么不隐藏foo(字符串)?感觉很不一致…不管我是否重写foo(int),结果都是一样的。有人能解释一下这是怎么回事吗?

(是的,我知道在派生类(liskov和all)中重载基方法是不好的做法,但是我仍然不希望在overridedEnderivedClass中调用foo(in t)?!)


要解释它如何在OverriddenDerivedClass示例中工作:

查看C规范以查找成员:http://msdn.microsoft.com/en-us/library/aa691331%28vs.71%29.aspx

这定义了如何完成查找。

特别是,请看这部分:

First, the set of all accessible (Section 3.5) members named N declared in T and the base types (Section 7.3.1) of T is constructed. Declarations that include an override modifier are excluded from the set.

在你的例子中,NFoo()。由于Declarations that include an override modifier are excluded from the set的原因,则将override Foo(int i)排除在机组之外。

因此,只剩下未被重写的Foo(double i),因此被调用的就是它。

这就是它在OverriddenDerivedClass示例中的工作方式,但这不是对DerivedClass示例的解释。

要解释这一点,请看规范的这一部分:

Next, members that are hidden by other members are removed from the set.

DerivedClass中的Foo(double i)Foo(int i)从基类中隐藏起来,因此从集合中移除。

这里的棘手之处在于:

All methods with the same signature as M declared in a base type of S are removed from the set.

你可能会说"但是等等!Foo(double i)Foo(int i)没有相同的签名,因此不应将其从集合中删除!".

但是,由于存在从int到double的隐式转换,因此认为它具有相同的签名,因此从集合中移除Foo(int i)