为什么这个 lambda 表达式无法编译?
Action a = () => throw new InvalidOperationException();
推测没问题,但我真的很感激 C# 语言规范或其他文档的参考。
是的,我知道以下内容是有效的并且可以编译:
Action a = () => { throw new InvalidOperationException(); };
我使用类似内容的上下文在这篇博文中有所描述。
嗯。我已经有了答案,但不太好。
我不相信有“扔”表达。有一个 throw statement,但不仅仅是一个表达式。将此与“Console.WriteLine()”进行比较,“Console.WriteLine()”是一个 void 类型的方法调用表达式。
同样,您不能将 switch 语句或 if 语句等单独作为 lambda 的主体。你只能有一个表达式或一个块(第 7.14 节)。
有什么帮助吗?
这是我的看法:
throw
是一个陈述,而不是一个表达。
以及参考:
12.3.3.11 抛出语句
对于以下形式的语句 stmt
throw expr;
v 的确定赋值状态 expr 的开头是相同的 作为 v 的确定赋值状态 在 stmt 的开头。
为了解释其本质,也许我们应该考虑一下表达式在 C# lambda 构造中意味着什么。它只是语法糖:
delegate () { return XXX; }
其中
XXX
是一个表达式
您无法从无作用域的 lambda 中返回或抛出。
这样想...如果您不提供 {},编译器将确定您的隐式返回值是什么。 当您在 lambda 中
throw
时,没有返回值。 你甚至不会回来void
。 我不知道为什么编译器团队不处理这种情况。
我可以从这里找到的所有参考资料:
http://msdn.microsoft.com/en-us/library/ms364047(VS.80).aspx#cs3spec_topic4
表明你有两个选择:
Action a = () => { throw new InvalidOperationException(); };
或
Action a = () => throw new InvalidOperationException()
记下缺失的;在最后。是的,这对我来说也毫无意义。他们在规范中给出的示例是:
x => x + 1 // Implicitly typed, expression body
x => { return x + 1; } // Implicitly typed, statement body
(int x) => x + 1 // Explicitly typed, expression body
(int x) => { return x + 1; } // Explicitly typed, statement body
(x, y) => x * y // Multiple parameters
() => Console.WriteLine() // No parameters
不知道这有多大帮助 - 我不知道你在什么上下文中使用它,并且不添加 ;最后在 C# 中没有意义
区别可能在于它是一个表达式主体 - 而不是一个语句 - 如果它没有 {}。这意味着你的 throw 在那里无效,因为它是一个语句,而不是一个表达式!
没什么大惊喜。 Lambda 表达式是“函数式”编程的一个方面。异常是“过程式”编程的一个方面。两种编程风格之间的 C# 网格并不完美。