截图说明了这一点。 我有截屏中看到的重载。当使用字符串作为第二个参数时,编译器应该确定第一个参数只能是Func而不是表达式。 但是编译器会抛出一个错误,说“带有语句体的lamda表达式”无法转换为表达式树'。
为什么编译器无法找出正确的过载?
明确的演员阵容无济于事。什么有效是当我创建一个类型为Func的局部变量,然后使用它。
使用的框架是FakeItEasy 1.24.0
修改:
以下是显示行为的代码:
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();
}
答案 0 :(得分:6)
问题不在于Matches
的调用中。它在CallTo
的调用中,需要Expression<Action>
。
显然Expression
不仅不能是带有语句体的lambda表达式,它也不能包含带有语句体的lambda表达式。
(我不确定你的“把lambda放在一个局部变量”解决方案是工作还是它只是欺骗编译器而且会在运行时失败。)
这是我放在一起的测试:
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"));
}
你的“将表达身体的lambda放在本地”的作品是否取决于FakeItEasy的实施方式。我怀疑它会在这里起作用,但在例如LINQ-to-SQL不会 - 它只是在运行时而不是在编译时失败。
我不确定这是编译器错误,规范错误还是理想的行为。在C#规范的第6.5节中我们有
某些lambda表达式无法转换为表达式树类型:即使转换存在,它也会在编译时失败。如果lambda表达式是这种情况:
•有一个块体
•包含简单或复合赋值运算符
•包含动态绑定表达式
•是异步
不说“包含无法转换为表达式树类型的lambda表达式”。