Expression/Func 重载的编译器错误
Compiler Error for Expression/Func overloads
屏幕截图说明了很多。
如屏幕截图所示,我有重载。当使用字符串作为第二个参数时,编译器应该弄清楚第一个参数只能是 Func 而不是表达式。
但是编译器会抛出一个错误 'A lamda expression with a statement body cannot be converted to an expression tree'。
为什么编译器无法计算出正确的重载?
显式转换没有帮助。有效的是当我创建一个 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"));
}
你的“将 expression-bodied 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 表达式”。
屏幕截图说明了很多。 如屏幕截图所示,我有重载。当使用字符串作为第二个参数时,编译器应该弄清楚第一个参数只能是 Func 而不是表达式。 但是编译器会抛出一个错误 'A lamda expression with a statement body cannot be converted to an expression tree'。
为什么编译器无法计算出正确的重载?
显式转换没有帮助。有效的是当我创建一个 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"));
}
你的“将 expression-bodied 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 表达式”。