我已经读过在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
是函数调用。
答案 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)
return
块中不允许 finally
。实际上,除了throw
之外,不允许使用流控制命令。所以没有return
,没有break
,没有任何内容。
和如果根本不执行finally
块,那么它将不会被称为finally
而是maybe
。保证finally
块被执行(除非你的VM耗尽RAM,有人从你的计算机上拔下插件等等),无论你做return
,throw
或try
(或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
块的语句。无论控制转移是由于执行break
,continue
,goto
还是return
语句,还是作为正常执行而发生的,都是如此从try
语句中传播异常的结果。
请注意,当控件离开try
语句且包含 return
时,它会显示。请注意,在某些情况下,控件不会留下try
语句:无限循环,Environment.FailFast
,OutOfMemoryException
,用户断开电源以及其他可能性。这些是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
。