Why does passing a method group to an overloaded method cause ambiguity when calling the method in a lambda does not in this case?
Asked Answered
C

1

6

Why can't the correct overload to be called be inferred on the line marked // Compiler Error in the code below when the type is correctly inferred in all the other cases?

public static class Code {

    private static void Main() {

        OverloadedMethod<string>(() => new Wrapper<string>()); // OK
        OverloadedMethod<string>(() => MethodReturningWrappedString()); // OK
        OverloadedMethod<string>((Func<Wrapper<string>>)MethodReturningWrappedString); // OK
        OverloadedMethod<string>(MethodReturningWrappedString); // Compiler Error

    }

    public static Wrapper<string> MethodReturningWrappedString() {
        return new Wrapper<string>();
    }

    public static void OverloadedMethod<T>(Func<Wrapper<T>> func) where T : class {
    }

    public static void OverloadedMethod<T>(Func<T> func) where T : class {
    }

    public struct Wrapper<T> where T : class {
    }

}

Here's the compiler error:

The call is ambiguous between the following methods or properties:
'Namespace.Code.OverloadedMethod<string>(System.Func<Namespace.Code.Wrapper<string>>)'
and 'Namespace.Code.OverloadedMethod<string>(System.Func<string>)'
Cyme answered 3/7, 2014 at 22:26 Comment(0)
A
2

Because the method group MethodReturningWrappedString can be converted to both a delegate of type Func<Wrapper<T>> and a delegate of type Func<U> for suitable values of T and U.

The overload resolution rules don't stipulate that the first conversion is strictly better than the second, so the conversion is ambiguous and results in a compiler error.

Anticipation answered 3/7, 2014 at 22:37 Comment(5)
Does the lambda "() => MethodReturningWrappedString()" use different rules then?Decree
So why is the generic constraint where T : class taken into account when a lambda is passed but not when the method group is passed?Cyme
But Wrapper<T> is a struct so it cannot satisfy Func<U> where U : classGaivn
@Craig: In that context there is no ambiguity for the call to Method -- there's only one overload, so that is selected.Anticipation
@mikez: Good catch, but delegate conversion for method groups doesn't take that into account.Anticipation

© 2022 - 2024 — McMap. All rights reserved.