This code is not compiled:
static class Foo
{
public static Bar Do(Func<Bar> f) => null;
public static Bar<TOut> Do<TOut>(Func<Bar<TOut>> f) => null;
}
public class Bar
{
}
public class Bar<TOut>
{
public static implicit operator Bar<TOut>(TOut i) => null;
}
// Here compiler complains:
// CS0029 Cannot implicitly convert type 'int' to 'Bar'
// CS1662 Cannot convert lambda expression to intended delegate type
// because some of the return types in the block
// are not implicitly convertible to the delegate return type
Foo.Do(() => 1);
My expectation would be that compiler sees the return type of the lambda and that no valid overload can be selected unless int
is converted to Bar<int>
.
However, I see that compiler resolves to the first method.
Which part of spec defines this behavior?
This is specified in Method Invocations, when the spec is talking about what method declarations count as a candidate for overload resolution, for an invocation of the form M(A)
:
The set of candidate methods for the method invocation is constructed. For each method
F
associated with the method groupM
:
- If
F
is non-generic,F
is a candidate when:
M
has no type argument list, andF
is applicable with respect toA
.- If
F
is generic andM
has no type argument list,F
is a candidate when:
- Type inference succeeds, inferring a list of type arguments for the call, and
- [...]
Just from those rules, we can see that the non-generic Do
is a candidate, and the generic Do
is not, because type inference fails. Try commenting out the non-generic Do
, and you will see that it says something like "type arguments cannot be inferred".