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

class Program
{
 public delegate void VoidMethodDelegate();
 public delegate int IntMethodDelegate();
 static void Main(string[] args)
 {
 Test(IntMethod);
 Test(VoidMethod);
 }
 static int IntMethod()
 {
 return 1;
 }
 static void VoidMethod()
 {
 }
 static void Test(VoidMethodDelegate method)
 {
 }
 static void Test(IntMethodDelegate method)
 {
 }
}

Я пытаюсь настроить перегруженный метод, который будет принимать два разных типа делегатов. Делегаты отличаются только типом возврата - в обоих случаях они не принимают входных параметров. Итак, в приведенном выше примере я хотел бы иметь возможность вызвать Test() и передать его либо методом, возвращающим void, либо методом, возвращающим int. Когда я компилирую код выше, я получаю следующие ошибки:

ошибка CS0121: вызов неоднозначен между следующими способами или свойства: 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.VoidMethodDelegate)' а также 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.IntMethodDelegate)'

ошибка CS0407: 'int ConsoleApplication1.Program.IntMethod()" имеет неправильный тип возврата

ошибка CS0121: вызов неоднозначен между следующими способами или свойства: 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.VoidMethodDelegate)' а также 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.IntMethodDelegate)'

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

static void Main(string[] args)
 {
 Test(new IntMethodDelegate(IntMethod));
 Test(new VoidMethodDelegate(VoidMethod));
 }

Но этот синтаксис беспорядочен, и я предпочел бы иметь возможность передать метод напрямую, вместо того, чтобы обернуть его при вызове new. Единственное решение, которое я видел, это избавиться от перегруженной версии Test() и вместо этого использовать два разных метода, каждый с другим именем.

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

1 ответ

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

Я думаю, что этот вопрос может быть уместным, но я еще не проверял.

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

РЕДАКТИРОВАТЬ: Я уверен, что другой вопрос SO актуальен, на самом деле. Я предлагаю вам взять себе чашку кофе, спецификацию С# 4, а затем внимательно прочитать Эрика. Затем измените имена методов, чтобы вам больше не пришлось об этом думать.

licensed under cc by-sa 3.0 with attribution.