是否执行finally块

  • 本文关键字:finally 执行 是否 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是一个函数调用。

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

try内的返回仍将导致finally块被执行。

至于您的第二种情况,一般来说,是的,您的finally块将执行。然而,如果您调用Environment.FailFast,则此方法具体为:

在不运行任何活动的try/finaly块或终结器的情况下终止进程。

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


如果您进行了编辑,将执行第一个finally块。

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

在第二个过程中,Environment.Exit将立即退出进程,而finally将不执行。注意,情况2中的catch块也将不执行,正如Environment.Exit的文档所指定的那样:

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

至于你的最后一行:

我的理解是,退出是一个系统调用,返回是一个函数调用。

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

情况1

将执行finally块。在正常情况下,finally块总是被执行。

文件上写着,我强调:

通常,finally块的语句在控件离开try语句时运行。控制权的转移可能是由于正常执行、break、continue、goto或return语句的执行,或者try语句外的异常传播。

情况2

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

文件并没有说明这一点。然而,我可以打赌,在对Environment.Exit()的调用中是对Win32 API函数ExitProcess()的调用,并且对该函数的调用永远不会返回。

return在C#finally块中是不允许的。事实上,除了throw之外,不允许任何流量控制命令。所以没有return,没有break,什么都没有。

并且如果finally块根本不被执行,那么它将不被称为finally,而是被称为maybe。无论您在执行returnthrow还是try(或catch)块中的任何其他操作,都保证执行finally块(除非您的虚拟机内存不足,或者有人从您的计算机上拔下插头等等)。

我读到finally块总是在try-catch块之后调用。

此语句为falsefinally块并不总是执行

请检查语言规范,8.10:

当控件离开try语句时,总是执行finally块的语句。无论控制转移是作为正常执行的结果,还是作为执行breakcontinuegotoreturn语句的结果,或者作为从try语句中传播异常的结果而发生,都是如此。

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

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

请注意,在第二种情况下,finally不会执行,因为控件不会离开try块。控制被立即终止。程序停止运行,没有要传输的控制。

来自Environment.Exit:的文档

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

关于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

最新更新