Search code examples
c#compiler-errorsdelegatesambiguous

Ambiguous C# method call with delegates


In my application, I have code similar to following:

class Program
    {
        static void Main(string[] args)
        {
            Method(uri => Task.FromResult(uri));
        }

        static void Method(Func<Uri, Uri> transformer)
        {
            throw new NotImplementedException();
        }

        static void Method(Func<Uri, Task<Uri>> transformer)
        {
            throw new NotImplementedException();
        }
    }

As expected, running this code calls the second overload of 'Method', the one expecting a function delegate that returns a task. However, if i change the code to avoid using the anonymous method in Main:

class Program
    {
        static void Main(string[] args)
        {
            Method(Method2);
        }

        static Task<Uri> Method2(Uri uri)
        {
            return Task.FromResult(uri);
        }

        static void Method(Func<Uri, Uri> transformer)
        {
            throw new NotImplementedException();
        }

        static void Method(Func<Uri, Task<Uri>> transformer)
        {
            throw new NotImplementedException();
        }
    }

The C# compiler now complains that my call to 'Method' is ambiguous. What am i missing?


Solution

  • The long answer is at https://stackoverflow.com/a/2058854/1223597 (as richzilla pointed out).

    The short answer is that the C# compiler team chose to make method group conversions (like Method(Method2)) ignore the return type (here of Method2). This gives them flexibility in how Expression trees are parsed. Unfortunately that means the compiler cannot implicitly choose between your 2 Method signatures.

    When doing a lambda conversion, (Method(uri => Task.FromResult(uri))), the compiler team doesn't need to worry about expression tree parsing, so they do consider return types.