Expression / Func重载的编译器错误

时间:2015-01-12 12:22:10

标签: c# lambda compiler-errors expression fakeiteasy

截图说明了这一点。 我有截屏中看到的重载。当使用字符串作为第二个参数时,编译器应该确定第一个参数只能是Func而不是表达式。 但是编译器会抛出一个错误,说“带有语句体的lamda表达式”无法转换为表达式树'。

为什么编译器无法找出正确的过载?

明确的演员阵容无济于事。什么有效是当我创建一个类型为Func的局部变量,然后使用它。

使用的框架是FakeItEasy 1.24.0

Wtf?

修改

以下是显示行为的代码:

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();
    }

1 个答案:

答案 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表达式”。