简体   繁体   English

在 .NET 中,如果 catch 块中出现故障,最终总是会被调用怎么办?

[英]In .NET, what if something fails in the catch block, will finally always get called?

In a try/catch/finally block like:在 try/catch/finally 块中,例如:

try
{

}
catch()
{
   // code fails here
}
finally
{ 

}

So if there is an exception in the catch block, will finally always get called?那么如果catch块中有异常,最终总是会被调用吗?

What if there is no finally, will the code after the catch block get run?如果没有 finally,catch 块之后的代码会运行吗?

Assuming the process doesn't terminate abruptly (or hang, of course), the finally block will always be executed.假设进程不会突然终止(当然也不会挂起),finally 块将始终被执行。

If there's no finally block, the exception from the catch block will just be thrown up the stack.如果没有 finally 块,catch 块中的异常将被抛出堆栈。 Note that the original exception which caused the catch block to be executed in the first place will be effectively lost.请注意,最初导致 catch 块执行的原始异常将被有效地丢失。

Stack overflow exceptions堆栈溢出异常

As Jared noted, a stack overflow will cause the finally block not to be executed.正如 Jared 所指出的,堆栈溢出将导致 finally 块不被执行。 I believe this terminates the program abruptly, but I could be wrong.我相信这会突然终止程序,但我可能是错的。 Here's sample code:这是示例代码:

using System;

public class Test
{    
    static void Main()
    {
        // Give the stack something to munch on
        int x = 10;
        try
        {
            Main();
            Console.WriteLine(x);
        }
        finally
        {
            Console.WriteLine("Finally");
        }
    }  
}

Results:结果:

Process is terminated due to StackOverflowException.进程因 StackOverflowException 而终止。

The finally block will always get executed. finally 块将始终被执行。 If you exclude the finally block, and an exception occurs inside the catch block, then no code after the catch block will execute, because essentially you're catch block will fail and generate an unhandled exception itself.如果您排除 finally 块,并且在 catch 块内发生异常,则 catch 块之后不会执行任何代码,因为本质上您的 catch 块将失败并自身生成未处理的异常。

Yes the finally will always be run是的,finally 将永远运行

No the code after the catch block won't be run.不,catch 块之后的代码将不会运行。

Even with a finally block any code following the finally block will not run.即使使用 finally 块,finally 块之后的任何代码都不会运行。

If there's an exception in the catch block, the finally will execute, but a new exception will be thrown.如果 catch 块中有异常,finally 会执行,但是会抛出一个新的异常。 The catch block in which the exception occurred will not catch the exception, it will continue up the stack.发生异常的 catch 块不会捕获异常,它会继续向上堆栈。

Lesson learned: don't do stuff in the catch block that can throw if you can help it;经验教训:如果你能帮助它,不要在 catch 块中做可以抛出的东西; if you must, nest a try/catch block.如果必须,请嵌套一个 try/catch 块。

try
{

}
catch()
{
  try
  {
    // code fails here
  }
  catch
  {
    // handle that. Or not. 
  }
}
finally
{ 

}

The finally block will always be executed. finally 块将始终被执行。 From MSDN :来自MSDN

The finally block is useful for cleaning up any resources allocated in the try block as well as running any code that must execute even if there is an exception. finally 块对于清理在 try 块中分配的任何资源以及运行任何必须执行的代码(即使存在异常)也很有用。 Control is always passed to the finally block regardless of how the try block exits.不管 try 块如何退出,控制总是传递给 finally 块。

Whereas catch is used to handle exceptions that occur in a statement block, finally is used to guarantee a statement block of code executes regardless of how the preceding try block is exited. catch 用于处理语句块中发生的异常,而 finally 用于保证语句块的执行,而不管前面的 try 块如何退出。

By the way, this is the type of question that you can easily test yourself by writing some code, compiling it, and seeing what happens when you execute it.顺便说一句,这是您可以通过编写一些代码、编译它并查看执行它时发生的情况来轻松测试自己的问题类型。

class Program {
    static void Main(string[] args) {
        try {
            Console.WriteLine("Trying!");
            throw new Exception();
        }
        catch (Exception e) {
            Console.WriteLine("Catching {0}!", e.Message);
            throw new Exception();
        }
        finally {
            Console.WriteLine("Finally!");
        }
    }
}

This outputs:这输出:

Trying!
Catching Exception of type 'System.Exception' was thrown.!

Unhandled Exception: System.Exception: Exception of type 'System.Exception' was
thrown.
at TestFinally.Program.Main(String[] args) in C:\Documents and Settings\Me\My
Documents\Visual Studio 2008\Projects\TestFinally\TestFinally\Program.cs:line 15
Finally!
Press any key to continue. . .

Just wanted to add the cases I'm aware about that will not allow the finally and any other code block execute:只是想添加我知道的不允许 finally 和任何其他代码块执行的情况:

  • In case of a runtime-thrown StackOverflowException在运行时抛出 StackOverflowException 的情况下
  • System.Environment.FastFail System.Environment.FastFail
  • Environment.Exit环境.退出
  • If a "background" thread is terminated because the main program to which it belongs is ending.如果一个“后台”线程因为它所属的主程序正在结束而终止。
  • Unexpected Shut Down:)意外关机:)

If an exception occurs in the catch block, all the code in finally would still be executed.如果 catch 块中发生异常,finally 中的所有代码仍然会被执行。 If there is an exception handler higher up in the stack (eg caller of this function), it will catch this exception.如果堆栈中有更高的异常处理程序(例如此函数的调用者),它将捕获此异常。 Else result in an unhandled exception and bring your app down.否则会导致未处理的异常并关闭您的应用程序。

The code after the point of exception in the catch block will not get called. catch 块中异常点之后的代码不会被调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM