在最后一个块中返回...为什么不呢?
正如 MSDN 提及:
Finally 块中的代码在 Try 或 Catch 中的 Return 语句 遇到块,但在此之前 返回语句执行。在这个 情况下,Return 语句 finally 块在 初始返回语句。这给出了 返回值不同。为防止 这种可能令人困惑的情况, 避免使用 Return 语句 最后阻塞。
由于我从这篇文章中没有理解很多内容,我将举一个例子(VB.NET,我认为在 C# 中情况是类似的):
Try
HugeOp()
Return "OK"
Catch
Return "NOK"
Finally
Return "Finally"
End Try
现在,为什么这在两者中都是非法的 C# 和 VB.NET?
As MSDN mentions:
The code in a Finally block runs after
a Return statement in a Try or Catch
block is encountered, but before that
Return statement executes. In this
situation, a Return statement in the
Finally block executes before the
initial Return statement. This gives a
different return value. To prevent
this potentially confusing situation,
avoid using Return statements in
Finally blocks.
As I didn't understand a lot from this note, I'll take an example (VB.NET, I think in C# is the situation is similar):
Try
HugeOp()
Return "OK"
Catch
Return "NOK"
Finally
Return "Finally"
End Try
Now, why should be this illegal in both C# and VB.NET?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是非法的,因为当您到达
Finally
块时,要返回的值已经定义(如果一切顺利,则返回“OK”;如果捕获异常,则返回“NOK”)。如果您能够从Finally
块返回不同的值,则无论上述指令的结果如何,都将始终返回该值。这只是没有意义...It's illegal because when you reach the
Finally
block, the value to return is already defined ("OK" if everything went well, "NOK" if an exception was caught). If you were able to return a different value from theFinally
block, this value would always be returned, whatever the outcome of the instructions above. It just wouldn't make sense...我想答案就在问题里。这是非法的,因为它令人困惑。将返回哪个值并不直观。如果它是非法的,您将被迫编写流程更清晰的代码。
I guess the answer is in the question. It's illegal because it's confusing. It's not intuitive which value will be returned. If it's illegal, you are forced to write code where the flow is much clearer.
我对此很好奇,我正在运行 VS2010 并且不允许在 finally 块中返回。这是我编译的代码
我编译了 DLL 以查看 MSIL,它看起来相当有趣,上面的代码基本上被重构为:
并进行测试,上面两个类的 MSIL 完全相同。
I was curious about this, I'm running VS2010 and does not allow a Return in the finally block. here is the code I compiled
I compiled the DLL to view the MSIL it looked rather interesting the above code basically gets refactored to this:
and testing this out, the MSIL for the above two classes is exactly the same.
finally
块中不允许使用return
语句的原因最终归结为这些结构的要点/目标。Finally
块是特殊的代码块,旨在始终在某些先前的控制结构完成执行之后从头到尾运行;它们主要用于“清理”类型的代码。如果我们采用提供的代码:
Finally
块将在Return
从Try
中执行 > 或Catch
。这确实意味着有一个
Return
会“总是返回相同的东西”,但它不仅如此 - 一个Return
已经发生在当前程序中!该指令究竟意味着什么?我们要回到哪里?在一般情况下,
Return
在Finally
中没有任何意义,因为有一条将控制权转移到这些块之外的语句 1) 与它们的目的相反,2) 很难甚至概念化,因为Finally
块在运行时打破了“标准”控制流,因为它们出现在某些先前控制结构的Return
之后。在 C# 中,
finally
块中不允许使用goto
,原因基本相同:在设计上,外部控制传输在finally
内是禁止的。JavaScript 可以作为一个例子,说明如果没有这条规则,事情会变得多么混乱: 在 JS 中,
finally
块在控制流语句之前立即执行(例如return代码>) 中
try
/catch
,但do允许return
在其内部 - 这将掩盖(覆盖)在
(如果存在)。try
/catch
中返回我认为,除了彻底禁止它之外,没有任何解决方案可以使问题变得混乱。
The reason that
return
statements aren't allowed infinally
blocks ultimately comes down to the point/ goal of those structures.Finally
blocks are special blocks of code intended to always run start to finish, after some previous control structure has finished executing; they're primarily for "cleanup"-type code.If we take the code provided:
The
Finally
block will be executed after theReturn
from either theTry
orCatch
.This does kind of mean that having a
Return
there would "always return the same thing", but it's more than that– aReturn
already happened in the current procedure! What should that instruction even mean? Where are we returning to?In the general case, a
Return
makes no sense within aFinally
because having a statement that transfers control outside of these blocks is 1) antithetical to their purpose, and 2) hard to even conceptualize, sinceFinally
blocks break the "standard" control flow when they run since they come after theReturn
of some previous control structure.In C#,
goto
s are disallowed infinally
blocks for essentially the same reason: external control transfer is just off limits withinfinally
by design.JavaScript can serve as an example here of how confusing things could be without this rule: in JS,
finally
blocks execute immediately before a control-flow statement (e.g.return
) intry
/catch
, but do allowreturn
s inside themselves– which will overshadow (override) thereturn
inside thetry
/catch
, if it exists.I'd argue there's no resolution to this problem that's not confusing, other than just outright disallowing it.