屏幕截图说明了很多。 如屏幕截图所示,我有重载。当使用字符串作为第二个参数时,编译器应该弄清楚第一个参数只能是 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();
}
最佳答案
问题不在对 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 节中,我们有
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
没有说“包含无法转换为表达式树类型的 lambda 表达式”。
关于c# - 表达式/函数重载的编译器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27901928/