The screenshot says it pretty much. I have the overloads as seen in the screenshot. When using a string as second parameter the compiler should figure out that the first argument can only be a Func and not an expression. But the compiler throws an error saying 'A lamda expression with a statement body cannot be converted to an expression tree'.
Why can't the compiler figure out the correct overload?
Explicit cast does not help. What works is when i make a local variable of type Func and then use this instead.
The framework used is FakeItEasy 1.24.0
EDIT:
Here is the code that shows the behavior:
public static void Main(string[] args)
{
//compiler error
A.CallTo(() => Main(A<string[]>.That.Matches(strings =>
{
return true;
}, "description")));
//compiles
Func<string[], bool> predicate = strings =>
{
return true;
};
A.CallTo(() => Main(A<string[]>.That.Matches(predicate, "description")));
Console.ReadLine();
}
The issue is not in the call to Matches
. It's in the call to CallTo
, which expects an Expression<Action>
.
Apparently an Expression
not only can't be a lambda expression with a statement body, it also can't contain a lambda expression with a statement body.
(I'm not sure whether your "put the lambda in a local variable" solution will work or whether it just tricks the compiler and will fail at runtime.)
Here's the test I put together:
static void Overloaded(Action a, string param) { }
static void Overloaded(Expression<Action> e) { }
static void CallToAction(Action a) { }
static void CallToExprAc(Expression<Action> a) { }
static void Main(string[] args)
{
// Works
CallToAction(() => Overloaded(() => { int i = 5; }, "hi"));
// Doesn't work - using the Expression overload
CallToAction(() => Overloaded(() => { int i = 5; }));
// Doesn't work - wrapped in an outer Expression
CallToExprAc(() => Overloaded(() => { int i = 5; }, "hi"));
}
Whether your "put the expression-bodied lambda in a local" works is up to how FakeItEasy is implemented. I suspect it'll work here, but something similar in e.g. LINQ-to-SQL wouldn't - it'd just fail at runtime rather than at compile time.
I'm not sure whether this is a compiler bug, a spec bug or desirable behaviour. In section 6.5 of the C# spec we have
Certain lambda expressions cannot be converted to expression tree types: Even though the conversion exists, it fails at compile-time. This is the case if the lambda expression:
• Has a block body
• Contains simple or compound assignment operators
• Contains a dynamically bound expression
• Is async
which doesn't say "contains a lambda expression that cannot be converted to an expression tree type".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With