我读到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
。无论您在执行return
、throw
还是try
(或catch
)块中的任何其他操作,都保证执行finally
块(除非您的虚拟机内存不足,或者有人从您的计算机上拔下插头等等)。
我读到finally块总是在try-catch块之后调用。
此语句为false。finally
块并不总是执行而。
请检查语言规范,8.10:
当控件离开
try
语句时,总是执行finally
块的语句。无论控制转移是作为正常执行的结果,还是作为执行break
、continue
、goto
或return
语句的结果,或者作为从try
语句中传播异常的结果而发生,都是如此。
请注意,当控件离开try
语句并且包含return
时,它会显示。请注意,在某些情况下,控制不会留下try
语句:无限循环、Environment.FailFast
、OutOfMemoryException
、用户断开电源以及其他可能性。在这些情况下,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
。