超载分辨率和虚拟方法 [英] Overload resolution and virtual methods

查看:104
本文介绍了超载分辨率和虚拟方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下code(这是一个有点长,但希望你可以遵循):

  A级
{
}B类:一
{
}C类
{
    公共虚拟无效美孚(B B)
    {
        Console.WriteLine(base.Foo(B));
    }
}D类:C
{
    公共覆盖无效美孚(B B)
    {
        Console.WriteLine(美孚(B));
    }    公共无效美孚(A一)
    {
        Console.WriteLine(美孚(A));
    }
}类节目
{
    公共静态无效的主要()
    {
        B B =新的B();
        D D =新D();
        d.Foo(二);
    }
}

如果你觉得这个程序的输出是美孚(B),那么你会是在同一条船上,我说:完全错误!事实上,它输出美孚(A)

如果我删除从 C 类的虚方法,然后将它按预期工作:美孚(二)是输出

为什么编译器选择需要的版本 A B 是更派生类<? / p>

解决方案

答案是在C#规范的第7.3节并的部分7.5.5.1

我打破了用来选择要调用的方法步骤。


  • 首先,集合( N =富)的T(声明的名为N的所有可访问成员 T = D类)和T的基本类型( C类)构造。 声明包括override修饰符被排除在集 D.Foo(B)是排除的)

      S = {C.Foo(B); D.Foo(A)}


  • 这组候选方法方法调用构造。同一套以M相关的方法,它是由previous成员查找发现开始,集缩减为那些适用相对于参数列表AL( AL = B <方法/ code>)。集合减少包括在集,其中T( T = D类)的类型应用以下规则每个方法TN,其中N的方法( N =富)声明:


    • 如果N是不适用关于AL(的第7.4.2.1 ),则N从集合中删除。


      • C.Foo(B)适用相对于AL

      • D.Foo(A)适用相对于AL

          S = {C.Foo(B); D.Foo(A)}



    • 如果N是适用对于AL(第7.4.2.1),然后点击在基本类型T的声明的所有方法从集合中删除即可。的 C.Foo(B)从集合中删除

        S = {D.Foo(A)}



在最后的赢家是 D.Foo(A)


如果抽象方法是从C删除

如果抽象方法是从C去除,初始设定为 S = {D.Foo(B) D.Foo(A)} 重载决议规则必须使用选择的最好的函数成员在该组。

在这种情况下,赢家是 D.Foo(B)

Consider the following code (it's a little long, but hopefully you can follow):

class A
{
}

class B : A
{
}

class C
{
    public virtual void Foo(B b)
    {
        Console.WriteLine("base.Foo(B)");
    }
}

class D: C
{
    public override void Foo(B b)
    {
        Console.WriteLine("Foo(B)");
    }

    public void Foo(A a)
    {
        Console.WriteLine("Foo(A)");
    }
}

class Program
{
    public static void Main()
    {
        B b = new B();
        D d = new D ();
        d.Foo(b);
    }
}

If you think the output of this program is "Foo(B)" then you'd be in the same boat as me: completely wrong! In fact, it outputs "Foo(A)"

If I remove the virtual method from the C class, then it works as expected: "Foo(B)" is the output.

Why does the compiler choose the version that takes a A when B is the more-derived class?

解决方案

The answer is in the C# specification section 7.3 and section 7.5.5.1

I broke down the steps used for choosing the method to invoke.

  • First, the set of all accessible members named N (N=Foo) declared in T (T=class D) and the base types of T (class C) is constructed. Declarations that include an override modifier are excluded from the set (D.Foo(B) is exclude)

    S = { C.Foo(B) ; D.Foo(A) }
    

  • The set of candidate methods for the method invocation is constructed. Starting with the set of methods associated with M, which were found by the previous member lookup, the set is reduced to those methods that are applicable with respect to the argument list AL (AL=B). The set reduction consists of applying the following rules to each method T.N in the set, where T (T=class D) is the type in which the method N (N=Foo) is declared:

    • If N is not applicable with respect to AL (Section 7.4.2.1), then N is removed from the set.

      • C.Foo(B) is applicable with respect to AL
      • D.Foo(A) is applicable with respect to AL

        S = { C.Foo(B) ; D.Foo(A) }
        

    • If N is applicable with respect to AL (Section 7.4.2.1), then all methods declared in a base type of T are removed from the set. C.Foo(B) is removed from the set

          S = { D.Foo(A) }
      

At the end the winner is D.Foo(A).


If the abstract method is removed from C

If the abstract method is removed from C, the initial set is S = { D.Foo(B) ; D.Foo(A) } and the overload resolution rule must be used to select the best function member in that set.

In this case the winner is D.Foo(B).

这篇关于超载分辨率和虚拟方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆