18

如果您运行下面的代码,它实际上会在每次调用 goto 之后执行 finally:

    int i = 0;
Found:
    i++;
    try
    {
        throw new Exception();
    }
    catch (Exception)
    {
        goto Found;
    }
    finally
    {
        Console.Write("{0}\t", i);
    }

为什么?

4

8 回答 8

36

以下文字来自C#语言规范8.9.3的goto语句


goto 语句执行如下:

  • 如果 goto 语句退出一个或多个带有相关 finally 块的 try 块,则控制最初转移到最里面的 try 语句的 finally 块。当控制到达 finally 块的终点时,控制将转移到下一个封闭 try 语句的 finally 块。重复此过程,直到所有介入的 try 语句的 finally 块都已执行。
  • 控制转移到 goto 语句的目标。
于 2009-07-17T05:37:40.530 回答
28

为什么你期望它不执行?

如果你有 try/catch/finally 或 try/finally 块,不管你在 try 或 catch 块中大部分时间有什么代码 ,finally 块都会执行。

考虑“返回”,而不是 goto。

//imagine this try/catch/finally block is inside a function with return type of bool. 
try
{
    throw new Exception();
}
catch (Exception)
{
    return false; //Let's say you put a return here, finally block still executes.
}
finally
{
    Console.WriteLine("I am in finally!");
}
于 2009-07-17T05:22:59.017 回答
14

给出的答案的要点 - 当控制通过任何方式离开受保护区域时,无论是“return”,“goto”,“break”,“continue”还是“throw”,“finally”都会被执行 - 是正确的。但是,我注意到几乎每个答案都说“finally 块总是运行”。 finally 块并不总是运行。在很多情况下,finally 块都不会运行。

谁想尝试将它们全部列出?

于 2009-07-17T07:16:01.550 回答
3

似乎有道理。finally块总是在或try之后运行catch

相似地

try
{
  // do something
  return;
}
finally
{
  // do something else
}

将始终运行该finally块。编辑 - 但请参阅上面 Eric 的评论。

于 2009-07-17T05:25:10.413 回答
2

这是设计使然。在异常处理程序中,您可以采取一些特定于异常的操作。在 finally 块中,您应该进行资源清理——这就是为什么无论异常处理代码是什么,都始终执行 finally 块的原因。

于 2009-07-17T05:24:03.350 回答
1

正如人们所提到finally的,无论程序流程如何,都会运行。当然,finallyblock 是可选的,所以如果你不需要它,就不要使用它。

于 2009-07-17T05:52:21.030 回答
0

因为一条finally语句预计在离开后try(或catch捕获异常时)执行。这包括您拨打 goto 电话的时间。

于 2009-07-17T05:26:25.263 回答
0

这就是finally区块的重点。它总是执行(几乎)。

于 2010-05-12T20:22:49.523 回答