为什么这“最终”执行?

时间:2009-07-17 05:20:14

标签: c# exception goto try-catch-finally

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

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

为什么?

8 个答案:

答案 0 :(得分:37)

以下文字来自 C#语言规范8.9.3 The goto statement


goto语句执行如下:

  • 如果goto语句退出一个或多个带有关联finally块的try块,则控制最初会转移到最里面的try语句的finally块。当控制到达finally块的结束点时,控制权转移到下一个封闭的try语句的finally块。重复此过程,直到执行了所有介入的try语句的finally块为止。
  • 控制转移到goto语句的目标。

答案 1 :(得分:28)

为什么你不期望它执行?

如果你有try / catch / finally或者try / finally阻止,那么无论你在try或catch块中使用什么代码 most of the time,finally块都会执行

考虑“返回”,而不是转到。

//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!");
}

答案 2 :(得分:13)

给出答案的要点 - 当控制通过任何方式离开受保护区域时,无论是“返回”,“转到”,“中断”,“继续”还是“抛出”,“最终”都被执行 - 是正确。但是,我注意到几乎每个答案都说“最后一块总是运行”。 finally块并不总是运行。在很多情况下,finally块不会运行。

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

答案 3 :(得分:3)

似乎合理。 finally块始终在trycatch之后运行。

类似地

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

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

答案 4 :(得分:2)

这是设计的。在异常处理程序中,您可以执行一些特定于异常的操作。在finally块中你应该进行资源清理 - 这就是为什么finally块总是被执行,无论异常处理代码是什么。

答案 5 :(得分:1)

正如人们所提到的,finally无论程序流程如何都会运行。当然,finally块是可选的,因此如果您不需要它,请不要使用它。

答案 6 :(得分:0)

因为finally语句在离开try(或catch时捕获到异常)后才会执行。这包括你打电话的时候。

答案 7 :(得分:0)

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