Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous call error with overloaded method that takes 2 delegates with different return types

Tags:

c#

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)
    {
    }
}

I am trying to set up an overloaded method that will take two different types of delegates. The delegates differ only by return type -- in both cases they take no input parameters. So in the example above, I would like to be able to call Test() and pass it either a method that returns void, or a method that returns int. When I compile the code above, I get these errors:

error CS0121: The call is ambiguous between the following methods or properties: 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.VoidMethodDelegate)' and 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.IntMethodDelegate)'

error CS0407: 'int ConsoleApplication1.Program.IntMethod()' has the wrong return type

error CS0121: The call is ambiguous between the following methods or properties: 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.VoidMethodDelegate)' and 'ConsoleApplication1.Program.Test(ConsoleApplication1.Program.IntMethodDelegate)'

I know I can work around the errors if I create the delegates with new instead of just passing the method directly, like this:

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

But that syntax is messy, and I'd prefer to be able to pass the method directly, instead of having to wrap it in a call to new. The only solution I've seen is to get rid of the overloaded version of Test() and instead use two different methods, each with a different name.

Can anyone tell me why the compiler is complaining that this is ambiguous? I don't understand whhy the compiler can't decide which of the two overloads to use.

like image 576
Kyle West Avatar asked Aug 10 '10 13:08

Kyle West


1 Answers

Basically this is a corollary of how overloading is performed, and how method group conversions are resolved. I can try to wade through the spec to find the exact reasons if you like, but the bad news is that's just the way it is. It's possible there's a compiler bug in this case, but it's more likely that it's just a tricky bit of the spec.

I think that this SO question may be relevant, but I haven't checked yet.

Rather than resolve it using new, I would suggest take the option of using different method names. Overloading has all kinds of sneaky corner cases - this one is at least relatively harmless in that it's causing a compile-time error rather than picking the overload you don't want at execution time. Removing overloading is often a good thing :)

EDIT: I'm pretty sure that other SO question is relevant, actually. I suggest you get yourself a cup of coffee, the C# 4 spec, and then read Eric's answer very carefully. Then change the method names so you don't have to think about it any more.

like image 186
Jon Skeet Avatar answered Oct 12 '22 03:10

Jon Skeet