Re[19]: Вопрос на интервью в избранное  новое всё   подписка   модер. 
От: nikov экспертMy buzz
Дата: 12.12.09 09:11
Оценка:92 (7)
_FR>>>>Конечно же, будет один!
N>>>И, увы, опять неверно.

ВВ>>Ну ты шайтан


ВВ>>Ошибка, что ли будет?


N>Нет. Какие еще варианты остались?


На самом деле результат будет 7 1.

При построении группы методов для overload resolution методы, имеющие модификатор override, игнорируются. Получается три метода Foo(int), Foo(long, long), Foo(object). Но применяется такое правило из спецификации C# 4.0:

For virtual and abstract members, the parameter names in overrides may be different from those in the declaration. For the purposes of overload resolution, the parameter names that apply are the ones that appear in the most specific override of the function member with respect to the static type of the target of the member access.


Static type у объекта, у которого вызывается метод — C. Значит, если какой-то из методов переопределен в классе C, то нужно взять имена параметров оттуда, а иначе — из исходной декларации в базовом классе B. Получается Foo(int y), Foo(long x, long y = 1), Foo(object x). При вызове передается один именованный аргумент x:1. Значит, у первого метода не задан обязательный параметр y, и применимыми окажутся методы Foo(long x, long y = 1), Foo(object x). Они оба определены в одном классе, поэтому нужно выбрать лучший из них, исходя из их сигнатуры и передаваемых аргументов. Это Foo(long x, long y = 1), так как неявное преобразование из 1 в long лучше, чем преобразование из 1 в object (потому что есть неявное преобразование из long в object, но не наоборот). Параметру y соответствует значение по умолчанию 1, но оно не влияет на overload resolution (потому что только явно указанные аргументы влияют). Таким образом, вызывается метод с сигнатурой Foo(long, long) и аргументами (1, 1). Так как этот метод виртуальный, а runtime тип объекта D, то в runtime вызывается метод с соответствующей сигнатурой в классе D, и печатает 7 1.