跳出了一个终结块

时间:2016-04-14 12:17:31

标签: c#

我正在寻找关键字或 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之外,此限制是否有例外?

5 个答案:

答案 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块不能包含breakgotocontinue,它们会将控件转移到finally块之外。
  • finally块不能包含return语句。

简而言之,finally块必须执行它的最后一行代码。

来源:https://msdn.microsoft.com/en-us/library/aa664733(v=vs.71).aspx

此外,根据C#规范,finally块始终在执行try块或catch块后执行。

因此,如果没有这些要求,那么可能存在与trycatch块一起出现的流语句的控制流冲突。

示例1

try
{
  // do something
  continue;
}
finally
{
  break;
}

在上面的例子中,try块表示流应该转到包含循环的顶部。但是finally块表示应该退出循环。

该怎么做?

示例2

try
{
  return 0;
}
finally
{
  return 1;
}

这里我们有相互冲突的返回值。

要返回哪个?

C#规范的编写者可能选择finally块的控制流覆盖trycatch块的控制流。但是对于编译器和调试来说,这会很复杂。

相反,他们决定保持简单,并通过禁止finally块之外的流量控制来完全避免它。

答案 4 :(得分:0)

您可以通过将标签放在 finally 块的末尾来实现,如下所示:

try
{
    ...
}
finally
{
    if (condition) goto ExitFinally;
    ...
    ExitFinally:
}