我正在寻找关键字或 clean 方式退出finally块而不使用选择语句。请考虑以下示例:
private bool AtteptToDoSomething()
{
try
{
MethodThatCouldFail();
return true;
}
catch
{
return false;
}
finally
{
//Jump out of function here?
//... to avoid executing this under certain conditions
DoSomethingFinalizing();
}
}
尝试不起作用:
finally
{
return;
break;
continue;
goto ExitSymbol;
//This works, but would require a second try-catch block
throw new Exception();
}
以上示例的编译器错误包括:
控制不能离开finally子句的主体
和
无法跳出finally块
现在很清楚,finally块无法通过任何常规方式转移控制。
有a pretty good explanation why this won't work with continue,但遗憾的是不能解释为什么在其他情况下无法做到这一点。
是否有任何(基于CLR或C#)原因导致不允许/不可能这样做?
除了throw之外,此限制是否有例外?
答案 0 :(得分:13)
你不能。
它的设计和它在C#规范中的描述:8.10 The try statement.
对于break,continue或goto语句来说,这是一个编译时错误 转移控制从最终块。休息时,继续,或 goto语句出现在finally块中,该语句的目标 必须在同一个finally块内,否则编译时 发生错误。
返回语句在a中发生是编译时错误 最后阻止。
为了做你想做的事,你可以做点什么:
try {}
catch {}
finally
{
Magic();
}
然后
void Magic()
{
if (x == y)
return;
else
a = b;
}
答案 1 :(得分:3)
好吧,你可以不执行块
...
finally
{
if (!certain conditions)
{
//... to avoid executing this under certain conditions
DoSomethingFinalizing();
}
}
答案 2 :(得分:1)
我知道这是一个老问题,但是我偶然发现了同样的情况,但是使用PHP。我无法跳出最后的障碍
PHP致命错误:不允许跳出finally块
由于您和我的朋友是计算机科学领域的好奇者,因此我发布了此答案,希望它能满足您的好奇心。
为什么无法跳出finally块?
简而言之,因为finally
不保证会处理该异常。
无论是否处理了异常,最终块都会始终执行,因此,如果您试图跳出finally块,则意味着您想做更多的事情,在这里做更多的事情就像您在尝试访问或处理不能保证存在的事物(因此没有意义)。
答案 3 :(得分:0)
C#规范表明如下:
finally
块不能包含break
,goto
或continue
,它们会将控件转移到finally
块之外。finally
块不能包含return
语句。简而言之,finally
块必须执行它的最后一行代码。
来源:https://msdn.microsoft.com/en-us/library/aa664733(v=vs.71).aspx
此外,根据C#规范,finally
块始终在执行try
块或catch
块后执行。
因此,如果没有这些要求,那么可能存在与try
或catch
块一起出现的流语句的控制流冲突。
try
{
// do something
continue;
}
finally
{
break;
}
在上面的例子中,try
块表示流应该转到包含循环的顶部。但是finally
块表示应该退出循环。
该怎么做?
try
{
return 0;
}
finally
{
return 1;
}
这里我们有相互冲突的返回值。
要返回哪个?
C#规范的编写者可能选择finally
块的控制流覆盖try
或catch
块的控制流。但是对于编译器和调试来说,这会很复杂。
相反,他们决定保持简单,并通过禁止finally
块之外的流量控制来完全避免它。
答案 4 :(得分:0)
您可以通过将标签放在 finally 块的末尾来实现,如下所示:
try
{
...
}
finally
{
if (condition) goto ExitFinally;
...
ExitFinally:
}