为什么我不能从表达式强健的成员中抛出异常? [英] Why can't I throw exceptions from an expression-bodied member?

查看:65
本文介绍了为什么我不能从表达式强健的成员中抛出异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用表达式主体成员,您可以将方法或属性的主体定义为不带return关键字(应该返回某些内容)的单个表达式.

Using expression-bodied members allows you to define the body of a method or property as a single expression without a return keyword (should it return something).

例如,它变成了这些

int Method1()
{
    return 5;
}

void Method2()
{
    Console.WriteLine();
}

进入这些

int Method1() => 5;

void Method2() => Console.WriteLine();

当您从身体抛出异常时,就会发挥不同的作用:

A difference comes into play when you throw an exception from the body:

void Method3()
{
    throw new Exception();
}

但是,以下内容将无法编译:

However, the following will not compile:

void Method3() => throw new Exception();

带有以下消息:

Warning The member 'Program.Exception()' does not hide an inherited member. The new keyword is not required.  
Error   'Program.Exception()' must declare a body because it is not marked abstract, extern, or partial  
Error   ; expected  
Error   Invalid token 'throw' in class, struct, or interface member declaration  
Error   Method must have a return type
Error   Invalid expression term 'throw' 


为什么?


Why?

推荐答案

之所以会发生这种情况,是因为前两个代码段( 5 Console.WriteLine )是表达式.更具体地说,它们分别是 NumericLiteralExpression InvocationExpression .

This happens because the first two code snippets (5 and Console.WriteLine) are expressions. More specifically these are respectively NumericLiteralExpression and InvocationExpression.

后一个( throw new Exception())是一条语句-在这种情况下为: ThrowStatement .

The latter one (throw new Exception()) is a statement -- in this case: ThrowStatement.

如果您查看Roslyn SDK,您会注意到 MethodDeclarationSyntax 对象具有 ArrowExpressionClauseSyntax 类型的属性 ExpressionBody 类型为 ExpressionSyntax 的属性.这应该很明显地表明,在表达式健全的成员中仅接受表达式.

If you look at the Roslyn SDK you'll notice that a MethodDeclarationSyntax object has a property ExpressionBody of type ArrowExpressionClauseSyntax which in turn has a property of type ExpressionSyntax. This should make it obvious that only expressions are accepted in an expression-bodied member.

如果查看最后一个代码示例,您会注意到它由 ThrowStatementSyntax 组成,而该代码又具有 ExpressionSyntax 属性.在我们的例子中,我们用 ObjectCreationExpressionSyntax 对象填充该对象.

If you look at the last code sample, you'll notice that it consists of a ThrowStatementSyntax which has in turn an ExpressionSyntax property. In our case we're filling that with an ObjectCreationExpressionSyntax object.

  • Expression Versus Statement [Stackoverflow]
  • Statements, Expressions, and Operators [MSDN]

我只能在这里猜测,但我认为这是因为那样会产生太多的副作用,以至于无法引发异常.我不认为表达式和语句在继承中有共同的祖先,因此会有很多代码重复.最后,我认为它归结为根本就不值得成为麻烦,尽管在某种意义上是有意义的.

I can only guess here but I would assume it's because that would open up way too many side-effects just to be able to throw an exception. I don't believe an expression and a statement have a common ancestor in the inheritance so there'd be a lot of code duplication. In the end I assume it boiled down to simply not worth being the hassle, even though it makes sense in a way.

当您将一个简单的表达式作为方法主体的一部分编写时,实际上它被包裹在 ExpressionStatementSyntax 下–是的,两者结合了!这使它可以与该方法的 Body 属性下的其他语句组合在一起.他们必须在引擎盖下展开并从中提取表达式.反过来,它也可以用于表示表达式的成员,因为此时您只剩下一个表达式,而不再是一个语句.

When you write a simple expression as part of a method body that gets in fact wrapped under a ExpressionStatementSyntax -- yes, both combined! This allows it to be grouped together with other statements under the Body property of the method. Under the hood, they must be unrolling this and extracting the expression from it. This in turn can be used for the expression-bodied member because at this point you're left with just an expression and no longer a statement.

然而,这里的一个重要说明是return语句是..语句.更具体地说,是 ReturnStatementSyntax .他们必须明确地处理此问题并应用了编译器魔术,但这确实引出了一个问题:为什么不对 ThrowStatementSyntax 进行相同的处理?

One important note here however is the fact that a return statement is.. a statement. More specifically a ReturnStatementSyntax. They must have handled this explicitly and applied compiler magic though that does beg the question: why not do the same for ThrowStatementSyntax?

请考虑以下情形:突然, throw 语句也被接受.但是,由于表达式主体成员只能将表达式作为其主体(duh),这意味着您必须省略 throw 关键字,而只剩下 new Exception().您将如何区分打算使用 return 语句和 throw 语句?

Consider the following scenario: suddenly, throw statements are accepted as well. However since an expression-bodied member can only have expressions as its body (duh) that means you have to omit the throw keyword and instead are left with new Exception(). How are you going to distinguish between intending a return statement and a throw statement?

这两种方法的表达体差异没有区别:

There would be no difference between the expression-bodied variation of these two methods:

public Exception MyMethod()
{
    return new Exception();
}

public Exception MyMethod()
{
    throw new Exception();
}

throw return 语句都是有效的方法结尾.但是,当您省略它们时,没有任何东西可以区分两者-ergo:您永远不会知道是返回还是抛出该新创建的异常对象.

Both a throw and a return statement are valid method-endings. However when you omit them there is nothing that distinguishes the two -- ergo: you would never know whether to return or to throw that newly created exception object.

表达式健全的成员的名称恰如其名:主体中只有一个表达式的成员.这意味着您必须知道什么构成了一个表达式.仅仅因为它是一个陈述"并不能使其成为一种表达.

An expression-bodied member is exactly as the name says it is: a member with only an expression in its body. This means that you have to be aware of what exactly constitutes an expression. Just because it's one "statement" doesn't make it an expression.

这篇关于为什么我不能从表达式强健的成员中抛出异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆