22

考虑以下分配给事件的 lambda 表达式。

foo.BarEvent += (s, e) => if (e.Value == true) DoSomething();

这看起来很简单,只包含一行代码。那么为什么我会从调试器中收到以下 2 个错误?

无效的表达式术语“如果”


只有 assignment、call、increment、decrement、await 和 new 对象表达式可以用作语句

要解决此问题,您所要做的就是将您的if语句括在括号中。

foo.BarEvent += (s, e) => { if (e.Value == true) DoSomething(); };
//Errors now disappear!

我了解这些错误消息的含义。我不明白为什么单条件if语句会成为编译器的问题,以及为什么第一个 lambda 赋值被认为是错误的。

有人可以解释这个问题吗?

4

4 回答 4

37

没有{ }你声明一个表达式体,{ }它就是一个语句体。请参阅Lambda 表达式(C# 编程指南)

  • 表达式lambda 返回表达式的结果

  • 语句lambda 类似于表达式 lambda,不同之处在于语句用大括号括起来 [...] 语句 lambda 的主体可以由任意数量的语句组成。

因此,如果您想要一个语句而不是表达式,请使用大括号。

于 2013-08-15T13:34:56.930 回答
9

请参阅Lambda 表达式

有两种类型的 Lambda,表达式 Lambda (no {}) 和 Statement Lambda (with {})。

它们之间的主要区别在于表达式 Lambda 被定义为返回由其右侧计算的值。但是if()是陈述,不是表达。没有与if. 您会注意到您提供的错误消息中的所有“允许”语言元素都是表达式:它们计算一个

于 2013-08-15T13:39:32.917 回答
0

据我了解,实现这一点不会有问题。C# 团队已经实现了更可怕的功能(例如 LINQ)

但问题是你在哪里画线?

如果

b => if (b) DoSomething()` 

是允许的,那么,为什么不应该

b => if (b) {DoSomething1(); DoSomething2();}

被)允许。或者

list => foreach (var item in list) DoSomething(item)

等等,等等,等等……在不知不觉中,你已经拥有了一个支持一个基本微不足道的功能的整个团队。

在功能中没有错误的唯一可靠方法是不实现该功能

当前的实现是最佳的,因为它在大多数情况下都有效,并且在其余情况下并不太麻烦(简单的 {} 不会过多地妨碍可读性,同时使编译器更容易)。

于 2013-08-15T13:41:16.910 回答
0

这样看。如果正确,您有一个条件语句会触发一行。

if (stuff) do stuff;

也可以写成

if (stuff)
     do stuff;

因为您只调用一行代码,所以不需要两个括号。如果它更多,那么你将不得不使用括号。

if (stuff)
{
     do stuff;
     do more stuff;
}

然后你将它与一个匿名方法结合起来,它的行为方式类似

() => do stuff;

不止一个语句,使用括号就像条件一样。

() => {do stuff; do more stuff;}

但是现在您正在嵌套它们,但仍然希望能够使用快捷方式。这就是它的真正含义,一种捷径,它暗示了一个语句的括号。

因此,您将一个快捷方式嵌套在另一个快捷方式中。C# 只是强迫你明确地拼出嵌套的快捷方式。

于 2013-08-15T13:41:46.490 回答