此声明不在VS2015中编译,但在VS2017中编译:
var example = new Action( () => throw new Exception()
为了支持在labmda表达式中抛出异常,解析labmdas的方式有什么变化?
特别是因为如果我使用lambda身体,VS2015非常高兴:
我的问题类似于Why can't I throw exceptions from an expression-bodied member?,但我的问题是为什么。从lambda创建表达式树需要扩展编译器会发生什么?
答案 0 :(得分:6)
在C#6中,() =>
必须后跟一个表达式。它可能是一个没有产生任何值的表达式,例如对返回类型为void
的方法的调用,但它仍然是一个表达式。
在C#6中,throw
只能出现在声明中。完整的throw new Exception("test");
是一个声明。注意那里的分号。语法中没有任何内容可以单独支持throw new Exception("test")
,分号是其中不可或缺的一部分。
因此,要使其工作,C#7必须允许() =>
之后的语句,并且需要支持一种语句而不终止;
,或者C#7需要扩展允许throw
出现在那里的表达式的定义。后者就是这样。
答案 1 :(得分:3)
C#没有考虑throw
有一个类型(甚至不是void
),所以throw
是一个声明,而不是一个表达式,因此没有任何意义要么用它创建一个lambda,要么用它作为一部分组成更大的表达式。
C#7允许它具有任何类型,因此现在都可以实现这两种类型。
答案 2 :(得分:1)
这是C#7.0的更新,请参阅有关“投掷表达式”的部分:https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/