【问题标题】:Compiler Error for Expression/Func overloads表达式/函数重载的编译器错误
【发布时间】:2015-03-10 05:10:41
【问题描述】:

截图说明了这一点。 如屏幕截图所示,我有重载。当使用字符串作为第二个参数时,编译器应该确定第一个参数只能是 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();
    }

【问题讨论】:

  • 你能把代码贴出来而不是截图吗?
  • 您不要在仅表达式的 lambda 正文中使用 return...string =&gt; true 就足够了。
  • @leppie:正确,但这不是重点。正如您在屏幕截图中看到的那样,编译器应该使用带有 Func 的重载,因此方法体应该没问题。编译器会给出错误。问题是为什么。
  • @leppie:第二个参数是一个字符串,因此表达式的重载应该不在图片中,因为这个重载只有一个参数。
  • @leppie:好点,但没有默认值。

标签: c# lambda compiler-errors expression fakeiteasy


【解决方案1】:

问题不在于对Matches 的调用。它在对CallTo 的调用中,它需要Expression&lt;Action&gt;。

显然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 表达式”。

【讨论】:

  • 啊..好点!是的,当你创建一个局部变量时,它也可以在运行时工作。谢谢!
  • @MarChr 很高兴听到它,而且是个好地方——当然是一个有趣的问题。
  • 是的,但现在也有意义。谢谢!
  • 因为我认为这是一个编译器错误,所以我提出了它here。
猜你喜欢
  • 2017-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多