Ambiguous call error with overloaded method that takes 2 delegates with different return types
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 de开发者_如何学Golegates 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.
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.
精彩评论