问题
This statement doesn't compile in VS2015, but does in VS2017:
var example = new Action( () => throw new Exception()
What had to change in the way labmdas are parsed in order to support throwing an exception inside a labmda expression?
Especially because if I use a lambda body, VS2015 is perfectly happy:
My question is similar to Why can't I throw exceptions from an expression-bodied member?, but my question, is why. What had to happen in the creation of an expression tree from a lambda that necessitated extending the compiler?
回答1:
In C# 6, () =>
had to be followed by an expression. It could be an expression that did not produce any value, such a call to a method with a return type of void
, but that's still an expression.
In C# 6, throw
could only appear in a statement. The complete throw new Exception("test");
is a statement. Note the semicolon in there. There was nothing in the grammar to support throw new Exception("test")
on its own, the semicolon was an integral part of it.
Therefore, to get this to work, either C# 7 would have to allow statements after () =>
and would need to support a form of statements without the terminating ;
, or C# 7 would need to extend the definition of an expression to allow throw
to appear there. The latter is what happened.
回答2:
C# didn't consider throw
as having a type (not even void
), so throw
was a statement, not an expression, and as such it made no sense to either create a lambda with it, or compose larger expressions with it as part.
C# 7 allows it to have any type, so both of these are now possible.
回答3:
It was an update in C# 7.0, see the part about "throw expressions": https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/
来源:https://stackoverflow.com/questions/44687456/why-is-throwing-an-exception-inside-lambda-a-c-sharp-7-feature