为什么不能从 finally 块的内部跳转到外部?
Why a jump cannot be made from the inside to the outside of a finally block?
为什么跳转(break
, continue
, goto
, return
) 不能从finally
块的内部跳转到外部(通过 throw
除外)?
Can anyone explain the technical reason?
没有,因为没有技术原因。完全有可能设计出允许分支离开 finally 的语言语义,而其他语言也允许这样做。可能会有一些小困难,因为 IL 中分支出现位置的规则对于 try-protected 区域是不同的,但这些很容易管理。
C# 不允许这种行为,因为如果它有这种特性,语言会更糟。从 finally 分支出来是一种糟糕的编程习惯,应该被禁止。
这样想。如果 finally 是 运行 因为异常,那么劫持与该异常相关的控制流是个坏主意; finally 的延续应该是实现定义的行为,如果异常未处理,在这种情况下它可以做任何事情,或者它应该是处理异常的 catch 块。 "cancel" 一个 "in-flight" 异常的唯一方法是抛出另一个异常并允许它被处理。
如果 finally 不是 运行 因为异常,那么你可以把你想要的控制流放在 try-finally 块之后。
因此,允许 finally 分支出来是错误的或不必要的。由于不需要从 finally 分支出来,而且这样做永远都是一个坏主意,因此应该将其定为非法。
是的,如果您尝试在 finally 中 return
,则会出现错误
CS0157 Control cannot leave the body of a finally clause
但除了埃里克的出色回答,我完全同意他的意见,还有一个解决方法可能:
void Main() {
MyFunction();
}
void MyFunction()
{
void FinalActions() // local function used in the finally block below
{
for (int i = 0; i < 100; i++)
{
if (i>10)
{
Console.WriteLine("more than 10 ... ending.");
// this RETURNS from the local function and hence ends the finally block
return;
}
}
}
// the try-catch-finally block where we're using FinalActions()...
try {
// whatever you want to do here
}
catch (Exception ex) {
// whatever you want to do here
Console.WriteLine(ex.ToString());
}
finally {
FinalActions(); // just invoke it, the rest is done there
}
}
局部函数FinalActions()
一旦i>10
通过使用关键字return
返回就结束——注意这段代码只是为了展示从技术上讲,你可以做什么,你不会这样编程(在 for 循环中你只会说 i <= 10
)。
当然还有其他关键字
break, continue, goto
也允许 在本地函数 FinalActions()
的上下文中,尽管我不鼓励使用 goto
.
注意:旧版本的 C# 编译器不支持本地函数,您必须使用当前版本。
为什么跳转(break
, continue
, goto
, return
) 不能从finally
块的内部跳转到外部(通过 throw
除外)?
Can anyone explain the technical reason?
没有,因为没有技术原因。完全有可能设计出允许分支离开 finally 的语言语义,而其他语言也允许这样做。可能会有一些小困难,因为 IL 中分支出现位置的规则对于 try-protected 区域是不同的,但这些很容易管理。
C# 不允许这种行为,因为如果它有这种特性,语言会更糟。从 finally 分支出来是一种糟糕的编程习惯,应该被禁止。
这样想。如果 finally 是 运行 因为异常,那么劫持与该异常相关的控制流是个坏主意; finally 的延续应该是实现定义的行为,如果异常未处理,在这种情况下它可以做任何事情,或者它应该是处理异常的 catch 块。 "cancel" 一个 "in-flight" 异常的唯一方法是抛出另一个异常并允许它被处理。
如果 finally 不是 运行 因为异常,那么你可以把你想要的控制流放在 try-finally 块之后。
因此,允许 finally 分支出来是错误的或不必要的。由于不需要从 finally 分支出来,而且这样做永远都是一个坏主意,因此应该将其定为非法。
是的,如果您尝试在 finally 中 return
,则会出现错误
CS0157 Control cannot leave the body of a finally clause
但除了埃里克的出色回答,我完全同意他的意见,还有一个解决方法可能:
void Main() {
MyFunction();
}
void MyFunction()
{
void FinalActions() // local function used in the finally block below
{
for (int i = 0; i < 100; i++)
{
if (i>10)
{
Console.WriteLine("more than 10 ... ending.");
// this RETURNS from the local function and hence ends the finally block
return;
}
}
}
// the try-catch-finally block where we're using FinalActions()...
try {
// whatever you want to do here
}
catch (Exception ex) {
// whatever you want to do here
Console.WriteLine(ex.ToString());
}
finally {
FinalActions(); // just invoke it, the rest is done there
}
}
局部函数FinalActions()
一旦i>10
通过使用关键字return
返回就结束——注意这段代码只是为了展示从技术上讲,你可以做什么,你不会这样编程(在 for 循环中你只会说 i <= 10
)。
当然还有其他关键字
break, continue, goto
也允许 在本地函数 FinalActions()
的上下文中,尽管我不鼓励使用 goto
.
注意:旧版本的 C# 编译器不支持本地函数,您必须使用当前版本。