C# и переменное количество параметров
Я попробовал следующий код:
class Program: ProgParent
{
public int Max(params int[] op)
{
return 0;
}
public int Max(int i, params int[] op)
{
return 1;
}
public int Max(int i, int j, params int[] op)
{
return 2;
}
public static void Main(string[] args)
{
System.Console.WriteLine((new Program()).Max(5, 6, 7, 8));
System.Console.ReadKey();
}
}
Он выполняет и использует наиболее специфичную доступную функцию. Но компилятор не выдает предупреждений или ошибок по этому поводу. Зачем?
2 ответа
Спецификация языка C# гласит:
При выполнении разрешения перегрузки метод с массивом параметров может быть применим либо в его нормальной форме [то есть, передавая массив], либо в его расширенной форме [т.е. передавая переменное число параметров]. Расширенная форма метода доступна только в том случае, если обычная форма метода недоступна, и только если метод с такой же сигнатурой, что и расширенная форма, еще не объявлен в том же типе ".
В двух словах (немного упрощенно): если разрешение перегрузки неоднозначно, компилятор выбирает перегрузку без параметров.
Я думаю, что причины этого решения (вместо того, чтобы делать код, подобный вашему, нелегальным) включают в себя:
- Если ваш метод имеет сигнатуру: void fn(params object[] p), вы хотите каким-то образом вызвать "нормальную форму" (передав объект []). Таким образом, компилятор должен обрабатывать неоднозначные случаи в любом случае.
- Создание временного массива намного дороже, чем вызов метода, поэтому вы можете захотеть создать перегрузки без параметров с 1,2,3 параметрами, которые ведут себя одинаково, но являются более эффективными. (например, String.Format)
Игнорирование ошибок сборки (которые я опишу опечатками) - какое предупреждение вы ожидаете или хотите? Он находит соответствующую перегрузку и использует ее...
Строго говоря, я могу вызывать различные перегрузки - передавая массивы, но да, использование не совсем понятно.
Без многократных перегрузок с params
этот шаблон довольно сильно используется в таких вещах, как string.Concat
и т. д. (что лежит в основе +
для струн под капотом).