-5

我读过那个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");
}

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

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

4

5 回答 5

11

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

根据设计,返回try仍然会导致finally块被执行。

至于你的第二种情况,一般来说,是的 - 你的finally块将执行。Environment.FailFast但是,如果您专门调用此方法:

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

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


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

在第一种情况下,returninsidetry将触发finally块执行。

第二种,Environment.Exit会立即退出进程,finally不会执行。请注意,情况 2 中的 catch 块也不会执行,因为Environment.Exit's 的文档指定:

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

至于你的最后一行:

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

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

于 2013-08-06T15:43:38.690 回答
5

情况一

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

文件说,我强调:

通常,finally 块的语句在控制离开 try 语句时运行。控制的转移可能是正常执行的结果,也可能是执行 break、continue、goto 或return语句的结果,或者是从 try 语句传播异常的结果。

情况2

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

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

于 2013-08-06T15:54:27.253 回答
4

returnfinally在 C#块中是不允许的。事实上,除了throw. 所以不return,不break,没有什么。

如果finally块根本不会被执行,那么它就不会被调用finally但是maybe. finally块保证被执行(除非你的虚拟机内存不足,有人从你的计算机上拔掉插头等等),不管你是在做什么returnthrow或者你的try(或catch)块内的任何其他东西。

于 2013-08-06T15:42:27.927 回答
1

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

这种说法是错误的。该finally块并不总是执行。

请检查语言规范,8.10:

finally块的语句总是在控制离开try语句时执行。无论控制转移是正常执行的结果,还是执行break, continue, goto, orreturn语句的结果,还是从语句中传播异常的结果,都是如此try

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

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

请注意,在第二种情况下,该finally不会简单地执行,因为控制不会离开 try 块。控制立即终止。程序停止运行,没有控制权被转移。

从文档中Environment.Exit

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

于 2013-08-06T16:02:48.407 回答
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

于 2017-09-12T15:15:49.190 回答