Подтвердить что ты не робот

Конфликт перегруженных методов с дополнительными параметрами

У меня есть два перегруженных метода, один с необязательным параметром.

void foo(string a)  { }  
void foo(string a, int b = 0) { }  

теперь я вызываю:

 foo("abc");

Интересно, что первая перегрузка называется. почему не вторая перегрузка с дополнительным значением, установленным в ноль?

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

В чем причина такого поведения? Почему команда С# определила его таким образом?

4b9b3361

Ответ 1

От MSDN:

Если два кандидата считаются одинаково хорошими, предпочтение отдается кандидату, который не имеет необязательных параметров, для которых аргументы были опущены в вызове. Это является следствием общего предпочтения в разрешении перегрузки для кандидатов, у которых меньше параметров.

Ответ 2

Перегрузка, которая не требует каких-либо дополнительных параметров, которые должны быть заполнены автоматически, предпочтительнее той, которая делает. Однако нет такого предпочтения между заполнением одного аргумента автоматически и заполнением более одного - например, это приведет к ошибке времени компиляции:

void Foo(int x, int y = 0, int z = 0) {}
void Foo(int x, int y = 0) {}
...
Foo(5);

Обратите внимание, что Foo (5, 5) будет разрешен во втором методе, потому что тогда он не требует, чтобы любые необязательные параметры были автоматически заполнены.

Из раздела 7.5.3.2 спецификации С# 4:

В противном случае, если все параметры MP имеют соответствующий аргумент, тогда как аргументы по умолчанию должны быть заменяется, по меньшей мере, одним необязательным параметр в MQ, то MP лучше, чем MQ.

Я думаю, что в большинстве случаев это поведение, которое большинство людей ожидало бы, если честно. Это становится странным, когда вы вводите методы базового класса в микс, но это всегда было так.

Ответ 3

Только представьте, было ли это наоборот. У вас была заявка. У него был метод:

void foo(string a)  { }   

Everyting работал нормально. Теперь вы хотите добавить еще одну перегрузку с дополнительным параметром:

void foo(string a, int b = 0) { }  

Boom! Все вызовы методов переходят к новому методу. Всякий раз, когда вы этого хотите или нет. Добавление перегрузки метода может вызвать неправильные вызовы методов по всему приложению.

С моей точки зрения, в этом случае у вас будет гораздо больше возможностей нарушить ваш (или чужой) код.

Кроме того, OptionalAttribute был проигнорирован в С# до версии 4.0, но вы можете его использовать. И некоторые люди использовали его в коде С# для поддержки определенных сценариев совместимости с другими языками, такими как Visual Basic или для взаимодействия с COM. Теперь С# использует его для дополнительных параметров. Добавление предупреждений/ошибок может привести к нарушению изменений для этих приложений.

Могут быть и другие причины, но это только то, что приходит мне на ум.