Неоднозначная ошибка вызова с перегруженным методом, который принимает 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.Программа.Тест(ConsoleApplication1.Программа.VoidMethodDelegate)' и 'ConsoleApplication1.Программа.Тест(ConsoleApplication1.Программа.IntMethodDelegate)'

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

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

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

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

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

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

1 ответов


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

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

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

EDIT: я уверен, что другой вопрос SO и актуально, на самом деле. Я предлагаю вам возьмите себе чашку кофе, спецификацию C# 4, а затем внимательно прочитайте ответ Эрика. Затем измените имена методов, чтобы больше не думать об этом.