Как C# выбирает с неопределенностью и параметрами
Скажем, у меня есть следующие методы:
public static void MyCoolMethod(params object[] allObjects)
{
}
public static void MyCoolMethod(object oneAlone, params object[] restOfTheObjects)
{
}
Если я сделаю это:
MyCoolMethod("Hi", "test");
какой из них называют и почему?
3 ответа
Это легко проверить - вызывается второй метод.
Что касается того, почему - в спецификации языка C# есть несколько довольно подробных правил о том, как разрешаются неоднозначные объявления функций. Есть много вопросов о SO окружающих интерфейсах, наследовании и перегрузках с некоторыми конкретными примерами того, почему вызываются разные перегрузки, но для ответа на этот конкретный случай:
C# спецификация - разрешение перегрузки
7.5.3.2 Лучший функциональный член
В целях определения лучшего члена функции создается урезанный список аргументов A, содержащий только сами выражения аргументов в порядке их появления в исходном списке аргументов.
Списки параметров для каждого из функций-кандидатов строятся следующим образом:
Расширенная форма используется, если функция-член была применима только в расширенной форме.
Необязательные параметры без соответствующих аргументов удаляются из списка параметров
Параметры переупорядочиваются так, чтобы они находились в той же позиции, что и соответствующий аргумент в списке аргументов.
И дальше...
Если последовательности типов параметров {P1, P2, …, PN} и {Q1, Q2, …, QN} эквивалентны> (т. Е. Каждый Pi имеет преобразование идентичности в соответствующую Qi), применяются следующие правила разрыва связи Для того, чтобы определить лучший член функции.
Если MP - неуниверсальный метод, а MQ - универсальный метод, то MP лучше, чем MQ.
В противном случае, если MP применим в своей нормальной форме, а MQ имеет массив параметров и применим только в расширенной форме, то MP лучше, чем MQ.
В противном случае, если MP имеет больше заявленных параметров, чем MQ, то MP лучше, чем MQ. Это может произойти, если оба метода имеют массивы параметров и применимы только в их развернутых формах.
Кажется, что в этом случае применяется правило разрыва жирных связей. В спецификации подробно описывается, как обрабатываются массивы params в нормальной и расширенной формах, но в конечном итоге практическое правило заключается в том, что наиболее специфическая перегрузка будет вызываться с точки зрения количества и типа параметров.
Во-вторых, компилятор сначала попытается выполнить сопоставление с явно объявленными параметрами, а затем обратится к коллекции параметров.
Эта перегрузка хитрая...
MyCoolMethod("Привет", "тест"), очевидно, вызывает 2-ю перегрузку, но
MyCoolMethod("Привет"); также вызывает 2-ю перегрузку. Я проверял это.
Возможно, поскольку оба входа являются объектами, компилятор предполагает, что все, что передается, будет массивом объектов и полностью игнорирует первую перегрузку.
Вероятно, это связано с разрешением элемента Better, упомянутым в womp http://msdn.microsoft.com/en-us/library/aa691338(v=VS.71).aspx