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

string[] Test1(string data)

А также

string[] Test1(params string[] input)

Когда я вызываю Test1("Single test data") с намерением вызвать второй метод, вызывается первый метод.

Почему компилятор не помечает этот сценарий, как это было бы для более очевидных сценариев конфликта перегрузки?

1
Tolu 30 Май 2023 в 19:33
4
Разрешение перегрузки в C# может быть сложным, но в этом случае первое, очевидно, лучшее совпадение ¯\_(ツ)_/¯. Если вы ожидаете, что это вызовет второй вариант, первый никогда не будет доступен.
 – 
Joel Coehoorn
30 Май 2023 в 19:38

2 ответа

Почему компилятор не помечает этот сценарий, как это было бы для более очевидных сценариев конфликта перегрузки?

Потому что правила языка предписывают этого не делать.

Для этого есть очень конкретное правило. Из раздела 12.6.4.3 Спецификация С# 7:

В противном случае, если Mᵢ применим в своей нормальной форме, а Mₑ имеет массив параметров и применим только в расширенной форме, то Mᵢ лучше, чем Mₑ.

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

6
Jon Skeet 30 Май 2023 в 19:38
Ну, я думаю, вопрос в том, почему эти правила были приняты в первую очередь?
 – 
bashis
30 Май 2023 в 19:41
2
@bashis: Я бы сказал, что правила описывают то, что требуется в 99% случаев. (В частности, если вы ожидаете, что Test1("Single test data") вызовет второй метод, как вы всегда будете вызывать второй метод? Второй метод легко вызвать, если вы действительно хотите - просто сконструируйте одноэлементный массив самостоятельно.)
 – 
Jon Skeet
30 Май 2023 в 19:48
Я не ожидаю, что это вызовет второй метод, я ожидаю, что это не скомпилируется как потенциально неоднозначный код. Может быть, это только я, но, прочитав блог Эрика Липперта, у меня возникло ощущение, что команда C# пытается предотвратить компиляцию кода, который может быть неверно истолкован разработчиком. Это конкретное правило, хотя и однозначное для компилятора, явно может быть неверно истолковано разработчиком.
 – 
bashis
30 Май 2023 в 20:04

Ключевое слово params предназначено для того, чтобы вы могли задавать методу произвольное количество параметров. То есть «Одиночные тестовые данные» — это ОДИН параметр, тогда как вторая перегрузка позволяет использовать только объект массива в качестве входных данных.

Вы должны дать ему массив строк для вызова второй перегрузки:


using System;
class HelloWorld {
  static void Main() {
    Test1("one", "two", "three");
  }
  static string[] Test1(string data) {
    Console.WriteLine("First overload");
    return new string []{""};
  }
  
  static string[] Test1(params string[] input) {
      foreach (string str in input)
    Console.WriteLine(str);
    Console.WriteLine("Second overload");
    return new string []{""};
  }
}

0
Hekke 30 Май 2023 в 20:10