【问题标题】:In .NET, what if something fails in the catch block, will finally always get called?在 .NET 中,如果在 catch 块中发生故障,最终总是会被调用怎么办?
【发布时间】:2009-02-24 15:03:28
【问题描述】:

在 try/catch/finally 块中,例如:

try
{

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

}

那么如果catch块中有异常,最终总会被调用吗?

如果没有finally,catch块后面的代码会运行吗?

【问题讨论】:

    标签: .net exception-handling


    【解决方案1】:

    假设进程不会突然终止(当然也不会挂起),finally 块将始终被执行。

    如果没有 finally 块,来自 catch 块的异常将被抛出堆栈。请注意,最初导致 catch 块被执行的原始异常将被有效地丢失。

    堆栈溢出异常

    正如 Jared 所指出的,堆栈溢出将导致 finally 块不被执行。我相信这会突然终止程序,但我可能是错的。这是示例代码:

    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");
            }
        }  
    }
    

    结果:

    由于 StackOverflowException 而终止进程。

    【讨论】:

    • 我相信真正的 Stack Overflow 异常也可以阻止 finally 运行。不过,我找不到这方面的文档。
    • @Jared:是的,我认为你很有可能是对的。 OutOfMemoryException 也是?不确定。将尝试复制。
    • 但是 StackOverflowException 会突然终止整个过程吗?如果是这样,它就在我的第一次检查之下。
    • 如果第二个框架发生 CLR 引发的 StackOverflowException,运行时会立即终止当前进程。它证明了在这种情况下没有任何已知的异常处理技术有效,但 ICLRPolicyManager 接口MSDN 暗示了这一事实。
    • 其他灾难性较小的异常,例如 System.ArgumentOutOfRangeException,会导致 finally 块中的代码无法执行,如本问题中的代码所示:stackoverflow.com/questions/19549613/… 似乎在C# finally 块中的代码在异常处理后运行。 (在 Java 中则相反,正如其他代码所证明的那样;任何一种方式都是可接受的设计决策。)
    【解决方案2】:

    finally 块总是会被执行。如果你排除了 finally 块,并且在 catch 块中发生了异常,那么在 catch 块之后不会执行任何代码,因为本质上你的 catch 块会失败并自己生成一个未处理的异常。

    【讨论】:

      【解决方案3】:

      是的,finally 会一直运行

      没有catch块后面的代码不会运行。

      即使使用 finally 块,finally 块之后的任何代码都不会运行。

      【讨论】:

        【解决方案4】:

        如果catch块中有异常,finally会执行,但是会抛出一个新的异常。发生异常的catch块不会捕获异常,它会继续向上堆栈。

        经验教训:如果你能帮助它,不要在 catch 块中做可以抛出的东西;如果必须,嵌套一个 try/catch 块。

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

        【讨论】:

          【解决方案5】:

          finally 块总是会被执行。来自MSDN

          finally 块可用于清理在 try 块中分配的任何资源,以及运行任何必须执行的代码,即使出现异常也是如此。不管 try 块如何退出,控制总是传递给 finally 块。

          catch 用于处理语句块中发生的异常,而 finally 用于保证语句块的执行,而不管前面的 try 块如何退出。

          顺便说一句,这种类型的问题您可以通过编写一些代码、编译它并查看执行它时发生的情况来轻松测试自己。

          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!");
                  }
              }
          }
          

          这个输出:

          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 . . .

          【讨论】:

            【解决方案6】:

            如果 catch 块中发生异常,finally 中的所有代码仍然会被执行。 如果堆栈中有更高的异常处理程序(例如此函数的调用者),它将捕获此异常。否则会导致未处理的异常并关闭您的应用程序。

            catch 块中异常点之后的代码不会被调用。

            【讨论】:

              【解决方案7】:

              只是想添加我知道的不允许 finally 和任何其他代码块执行的情况:

              • 如果发生运行时引发的 StackOverflowException
              • System.Environment.FastFail
              • 环境.退出
              • 如果“后台”线程因主程序而终止 它所属的结局。
              • 意外关机:)

              【讨论】:

                猜你喜欢
                • 2013-09-19
                • 1970-01-01
                • 2014-01-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-03-11
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多