Итак, вот как это должно работать в соответствии со спецификацией (во время компиляции и с учетом правильной навигации по документам):
Компилятор определяет список подходящих методовиз типа D
и его базовых типов на основе имени метода и списка аргументов.Это означает, что любой метод с именем Foo
, принимающий один параметр типа, в который происходит неявное преобразование из B
, является допустимым кандидатом.Это приведет к следующему списку:
C.Foo(B) (public virtual)
D.Foo(B) (public override)
D.Foo(A) (public)
Из этого списка любые объявления, содержащие модификатор переопределения, исключаются.Это означает, что список теперь содержит следующие методы:
C.Foo(B) (public virtual)
D.Foo(A) (public)
На данный момент у нас есть список подходящих кандидатов, и теперь компилятор должен решить, что вызывать.В документе 7.5.5.1 Вызовы методов мы находим следующий текст:
Если N применимо по отношению к A ( Раздел 7.4.2.1 ), тогда все методы, объявленные в базовом типе T, удаляются из набора.
По сути это означает, что если в D
объявлен применимый метод, любые методы из базовых классов будут удаленыиз списка.На данный момент у нас есть победитель:
D.Foo(A) (public)