C#中选择不同的方法,以一个预期的使用可选参数和多层次的继承可选、多层次、不同、参数

2023-09-03 17:50:20 作者:孤岛情人

在给定的例子(对不起,code的风格,它是在一个紧凑的自包含摄制的利息),调用的方法始终是虚拟的方法B中具有更多的整型参数,虽然我预计,在 C 实施该方法将是一个叫。

In the given example (sorry for code style, it was in the interest of a compact self-contained repro), the method called is always the virtual method in B that has the additional integer parameter, while I would expect that the method implemented in C would be the one called.

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!");
        }
    }
}

它输出新基础。这显然​​不是我想象的行为,有没有人能够解释的理由?

Which outputs "base new". This is obviously not the behaviour I expected, is anyone able to explain the reasoning?

编辑: 更改主让 CM 有一个真正的或空参数仍选择不正确的方法。

Changing main so that c.M has a true or null parameter still selects the incorrect method.

推荐答案

该规范规定,重写方法被排除在一组中成员查找正在考虑访问的方法的第7.4节。考虑到原来的问题的方法,A类有一个单一的非覆盖的方法,B类有一个单一的非覆盖的方法,和C类可是没有任何。从该组中的两种方法,编译器选择在最派生类的匹配方法(在这种情况下B类中,基础新功能)。

Section 7.4 of the spec states that override methods are excluded from the set of accessible methods being considered during member lookup. Considering the methods in the original question, class A has a single non overridden method, class B has a single non overridden method, and class C doesnt have any. From the two methods in the set, the compiler selects the matching method in the most derived class (in this case class B, the "base new" function).

如果类B中的匹配函数不是present,最好函数匹配将是虚拟函数在A级。在这种情况下,作为虚拟的对象的运行时类型将被用于选择在任一A类重写功能,B或C将选择。其中的问题是说,因为该方法被称为C类的一个对象,将是接我!功能。

If the matching function in class B were not present, the best function match would be the virtual function in class A. In that case, being virtual, the run time type of the object would be used to select which of the overridden functions in either class A, B or C would be chosen. Which as the question was stated, as the method was called on an object of class C, would be the "pick me!" function.