Конфликт перегруженных методов с дополнительными параметрами
У меня есть два перегруженных метода, один с необязательным параметром.
void foo(string a) { }
void foo(string a, int b = 0) { }
теперь я вызываю:
foo("abc");
Интересно, что первая перегрузка называется.
почему не вторая перегрузка с дополнительным значением, установленным в ноль?
Честно говоря, я бы ожидал, что компилятор принесет ошибку, по крайней мере предупреждение, чтобы избежать непреднамеренного выполнения неправильного метода.
В чем причина такого поведения? Почему команда С# определила его таким образом?
Ответы
Ответ 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. Теперь С# использует его для дополнительных параметров. Добавление предупреждений/ошибок может привести к нарушению изменений для этих приложений.
Могут быть и другие причины, но это только то, что приходит мне на ум.