Lambda conversions with unclear return type and ov

2019-02-21 16:29发布

问题:

This question already has an answer here:

  • Peculiar overload resolution with while (true) 1 answer

If I have a lambda such as () => { throw new Exception(); }, it's unclear whether it has a return type or not. Because of this, it can be (implicitly) converted to both Action and Func<object> (or any other Func<T>). This is because, according to §6.5 Anonymous function conversions of the C# 4 spec:

[A] delegate type D is compatible with an anonymous function F provided:

  • If D has a void return type and the body of F is a statement block, when […] the body of F is a valid statement block in which no return statement specifies an expression.

  • If D has a non-void return type and the body of F is a statement block, when […] the body of F is a valid statement block with a non-reachable end point in which each return statement specifies an expression that is implicitly convertible to the return type of D.

But if I have two overloads of a method, where one has a parameter of type Action and the other Func<object>, and I pass it the lambda from above, the Func<object> overload is used. Why? Which part of specification says that Func<object> is better than Action in this case?

I have looked at §7.5.3.2 Better function member, but that does not explain it.

回答1:

I should've looked one section lower: §7.5.3.3 Better conversion from expression explains that:

Given an implicit conversion C1 that converts from an expression E to a type T1, and an implicit conversion C2 that converts from an expression E to a type T2, C1 is a better conversion than C2 if at least one of the following holds:

  • E is an anonymous function, T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2> and one of the following holds:

    • D1 and D2 have identical parameter lists, and one of the following holds:

      • D1 has a return type Y, and D2 is void returning