Почему этот метод называется?

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new Derived();
            int x = 123;
            a.Foo(x);
        }
    }

    public class Base
    {
        public virtual void Foo(int x)
        {
            Console.WriteLine("Base::Foo");
        }
    }

    public class Derived : Base
    {
        public override void Foo(int x)
        {
            Console.WriteLine("Derived::Foo(int x)");
        }

        public void Foo(object o)
        {
            Console.WriteLine("Derived::Foo(object o)");
        }
    }
}

Результат: "Производный:: Foo (объект o)"

ПОЧЕМУ???

Ответы

Ответ 1

Когда компилятор пытается найти кандидатские сигнатуры метода при подготовке к перегрузке, он сначала смотрит на наиболее производный тип и удаляет переопределенные методы, смотрящие только на "только что объявленные" подписи в этом классе.

Если он найдет применимый метод, он не продвинется дальше цепочкой наследования, чтобы найти другие подписи. Это противоречиво (по крайней мере, против моей интуиции) в такой ситуации. Он предназначен для предотвращения проблемы "хрупкого базового класса", когда изменение базового класса неожиданно влияет на другой код, но когда метод фактически переопределяется в производном классе, я не вижу преимущества. (По общему мнению, игнорировать это означало бы, казалось бы, методы no-op, которые переопределяли метод только для вызова базовой реализации, были почти такими же безопасными, как вы могли бы ожидать.)

У меня есть довольно длинная статья, которая перегружается с определенной детализацией об этой ситуации и других случаях в углу - вы можете счесть ее полезной. Подробнее см. В разделе 7.5.3 спецификации С#.

Нижняя строка: будьте осторожны с перегрузкой, особенно через границы наследования.