finally块会被执行吗?

时间:2013-08-06 15:40:48

标签: c#

我已经读过在finally块之后始终调用try catch块。

我有一种情况(请不要在语法上去)

情况1: -

try
{    
  return 1;
}
catch()
{
  return 2;
}
finally()
{
  Console.WriteLine("ABCD");
}

另一种情况是: -

情况2: -

try
{
  System.Environment.Exit(1);
}
catch()
{
   return 2;
}
finally()
{
  Console.WriteLine("ABCD");
}

我的问题是,如果我的代码进入try块,在这两种情况下都会执行finally块吗? 如果没有,请解释原因。

我的理解是exit是系统调用,return是函数调用。

5 个答案:

答案 0 :(得分:11)

两个示例都不会编译,因为finally块中不允许return语句。这意味着你的第一种情况是不可能的,而且确实不需要解决。

try内的返回仍然会导致finally块被设计执行。

至于你的第二种情况,一般来说,是的 - 你的finally块将会执行。但是,如果您致电Environment.FailFast,则此方法具体为:

  

终止进程而不运行任何活动的try / finally块或终结器。

在这种情况下,不会发生finally块。请注意,“退出”流程的其他方法(例如Environment.Exit(或Application.Shutdown类型调用))通常执行finally块中的代码。< / p>


鉴于您的编辑,将执行第一个finally块。

在第一种情况下,return中的try将触发finally块执行。

在第二个中,Environment.Exit将立即退出进程,并且finally将不会执行。请注意,情境2中的catch块将执行,因为Environment.Exit's documentation指定:

  

如果从try或finally块调用Exit,则任何catch块中的代码都不会执行。如果使用return语句,catch块中的代码将执行。

关于你的最后一行:

  

我的理解是exit是系统调用,return是函数调用。

这不是真的。 return不是函数调用,它是控制流指定的jump statement语言。 Environment.Exit实际上是一个方法调用(Exit类中的Environment方法)。

答案 1 :(得分:4)

C#return块中不允许

finally。实际上,除了throw之外,不允许使用流控制命令。所以没有return,没有break,没有任何内容。

如果根本不执行finally块,那么它将不会被称为finally而是maybe。保证finally块被执行(除非你的VM耗尽RAM,有人从你的计算机上拔下插件等等),无论你做returnthrowtry(或catch)区块内的任何其他内容。

答案 2 :(得分:4)

情况1

将执行finally块。在正常情况下,始终会执行finally块。

我强调documentation说:

  

通常,当控件离开try语句时,finally块的语句会运行。控制权的转移可以是正常执行,执行中断,继续,转到或返回语句,或者从try语句中传播异常的结果。

情况2

这不是正常情况。对Environment.Exit()的调用会立即终止进程,并且不会执行finally块。

文档没有说清楚。但是,我准备打赌在Environment.Exit()的调用内部是对Win32 API函数ExitProcess()的调用,并且对该函数的调用永远不会返回。

答案 3 :(得分:1)

  

我已经读过在try catch块之后总是调用块。

此声明为 false finally始终执行。

请检查语言规范,8.10:

  

当控件离开finally语句时,始终会执行try的语句。无论控制转移是由于执行breakcontinuegoto还是return语句,还是作为正常执行而发生的,都是如此从try语句中传播异常的结果。

请注意,当控件离开try语句且包含 return时,它会显示。请注意,在某些情况下,控件会留下try语句:无限循环,Environment.FailFastOutOfMemoryException,用户断开电源以及其他可能性。这些是finally 执行的情况。

特别是,在您的第一种情况下,finally执行非常简单,因为控制通过try离开return语句,并且规范,将执行。

请注意,在第二种情况下,finally将不会执行非常简单,因为控件不会离开try块。控制权立即终止。程序停止运行,无法控制转移。

来自Environment.Exit的文档:

  

退出会立即终止应用程序,即使其他线程正在运行。如果在应用程序入口点调用return语句,则会导致应用程序仅在所有前台线程终止后终止。

答案 4 :(得分:0)

还有另一个关于Environment.Exit的有趣案例,这里没有讨论过。如果不同的线程(从一个Environment.Exit调用)是在try子句的中间,该怎么办?文档没有说明会发生什么,但根据我的简单测试,答案仍然是没有 - finally块没有被执行:

var mre = new ManualResetEvent(false);

Console.WriteLine("starting task...");
Task.Run(() =>
{
    try
    {
        mre.Set();
        Console.WriteLine("sleeping...");
        Thread.Sleep(9999);
        Console.WriteLine("woke up");
    }
    finally
    {
        Console.WriteLine("finally");
    }
});

Console.WriteLine("waiting for task to get inside the try clause...");
mre.WaitOne();
Console.WriteLine("Task entered try clause, exiting...");
Environment.Exit(0);

输出将是:

  

开始任务......

     

等待任务进入try子句......

     

睡觉......

     

任务已输入try子句,退出...

正如您所见,没有finally