考虑以下分配给事件的lambda表达式。
foo.BarEvent += (s, e) => if (e.Value == true) DoSomething();
这看起来很简单,只包含一行代码。那么为什么我从调试器中得到以下2个错误?
无效的表达式术语'if'
只有赋值,调用,递增,递减,等待和新对象表达式才能用作语句
要解决此问题,您只需将if
语句包装在括号中即可。
foo.BarEvent += (s, e) => { if (e.Value == true) DoSomething(); };
//Errors now disappear!
我理解这些错误消息的含义。我不明白的是为什么单条件if
语句会成为编译器的问题,以及为什么第一个lambda赋值被认为是破坏的。
有人可以解释一下这个问题吗?
答案 0 :(得分:37)
如果没有{ }
,则声明一个表达式正文,{ }
它是一个声明正文。见Lambda Expressions (C# Programming Guide):
expression lambda返回表达式的结果
statement lambda类似于表达式lambda,除了语句括在括号中[...]语句lambda的主体可以包含任意数量的语句。
因此,如果您需要语句而不是表达式,请使用大括号。
答案 1 :(得分:9)
有两个类型的lambdas,Expression Lambdas(无{}
)和Statement Lambdas(带{}
)。
它们之间的主要区别在于Expression Lambdas被定义为返回由右侧计算的值。但是if()
是一个陈述,而不是表达。没有与if
相关联的值。您会注意到您提供的错误消息中的所有“允许”语言元素都是表达式:它们计算值。
答案 2 :(得分:0)
据我了解,实现这一点不是问题。 C#团队已经实现了更加可怕的功能(例如LINQ)
但问题是你在哪里画线?
如果
b => if (b) DoSomething()`
是允许的,那么,为什么不应该
b => if (b) {DoSomething1(); DoSomething2();}
被允许。或者
list => foreach (var item in list) DoSomething(item)
等等等......
在你知道它之前,你有一个完整的团队支持一个基本上微不足道的功能。
唯一确定功能中存在错误的方法是not implement the feature。
当前的实现是最佳的,因为它适用于大多数情况,并且它在其余部分中并不太麻烦(简单的{}不会过多地妨碍可读性,同时使编译器更容易)。
答案 3 :(得分:-1)
这样看待这个。你有一个条件语句,如果正确的话会触发一行。
if (stuff) do stuff;
也可以写
if (stuff)
do stuff;
因为您只调用一行代码,所以不需要两个括号。如果它更多,那么你将不得不使用括号。
if (stuff)
{
do stuff;
do more stuff;
}
然后你将它与匿名方法结合起来,行为方式类似
() => do stuff;
多个语句使用括号,就像条件一样。
() => {do stuff; do more stuff;}
但是现在你正在筑巢,但仍然希望能够使用捷径。 这究竟是什么,一个捷径暗示了一个单一陈述的括号。
因此,您在另一个快捷方式中嵌套了一个快捷方式。 C#只是强迫你明确拼出嵌套的快捷方式。