【问题标题】:In C# will the Finally block be executed in a try, catch, finally if an unhandled exception is thrown? [duplicate]在 C# 中,如果抛出未处理的异常,Finally 块是否会在 try、catch、finally 中执行? [复制]
【发布时间】:2010-10-24 10:52:12
【问题描述】:

【问题讨论】:

  • 这是一模一样的……我想知道为什么它还没有关闭。
  • 如果一个人用catch来捕捉X并做一些事情,那么finally还剩下什么?
  • @mP:如果需要的话,清理一下烂摊子:)
  • 通过meta.stackexchange.com/questions/97222/… 取消删除请在删除此内容或任何相关的欺骗之前阅读讨论并做出贡献。谢谢。

标签: c# .net finally


【解决方案1】:

finally大部分时间都会执行。这几乎是所有情况。例如,如果在线程上抛出异步异常(如StackOverflowException、OutOfMemoryException、ThreadAbortException),则无法保证finally 的执行。这就是为什么 constrained execution regions 存在用于编写高度可靠的代码的原因。

出于面试目的,我希望这个问题的答案是错误(我不能保证任何事情!面试官自己可能不知道这一点!)。

【讨论】:

  • 非常有趣,以前从未听说过 CER。感谢您在这里提出。
  • +1 这是一个经常被忽略且非常重要的点!由于您指出的原因,说“终于”总是执行是危险的。很好的答案。
  • 完全同意。我认为问题的根源在于 MSDN 本身。它应该在诸如已接受答案中提到的链接中提高对这一事实的认识。当 MSDN 本身说..“finally 用于保证语句块的执行,而不管前面的 try 块如何退出”这是错误的,这将是结果。我知道很少人不回答这个问题。
  • 我看到有人在做作业,很好的答案!一篇非常有趣的文章。
  • 另外,不要忘记更常见的情况,因为断电、硬件故障、操作系统杀死进程等原因导致它无法执行。如果你写了一半敏感文件和操作系统杀死你,finally 块不会拯救你。
【解决方案2】:

通常finally 块保证执行。

但是,在少数情况下,CLR 会在出现错误时强制关闭。在这些情况下,finally 块不会运行。

一个这样的例子是存在 StackOverflow 异常。

例如在finally 块下面的代码中没有执行。

static void Main(string[] args) {
   try {
      Foo(1);
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public static int Foo(int i) {
   return Foo(i + 1);
}

我知道的另一种情况是终结器是否抛出异常。在这种情况下,进程也会立即终止,因此保证不适用。

下面的代码说明了问题

static void Main(string[] args) {
   try {
      DisposableType d = new DisposableType();
      d.Dispose();
      d = null;
      GC.Collect();
      GC.WaitForPendingFinalizers();
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public class DisposableType : IDisposable {
   public void Dispose() {
   }

   ~DisposableType() {
      throw new NotImplementedException();
   }
}

在这两种情况下,进程都会在catch 和finally 之前终止。

我承认这些例子非常做作,但它们只是为了说明这一点。

幸运的是,这两种情况都不经常发生。

【讨论】:

  • 有趣的一点,但应该注意的是,第二个示例没有捕获异常,因为它发生在不同/未受保护的线程上。
  • +1 以 StackOverflow 为例 :-)
【解决方案3】:

直接来自 MSDN:

finally 块对 清理分配的任何资源 尝试块。控制总是 无论如何都传递给finally块 try 块是如何退出的。

而 catch 用于处理 语句中出现的异常 块,finally 用于保证一个 语句块代码执行 不管前面怎么尝试 块已退出。

http://msdn.microsoft.com/en-us/library/zwc8s4fz(VS.71,loband).aspx

【讨论】:

【解决方案4】:

是的,finally 总是被执行。

【讨论】:

    【解决方案5】:

    finally 总是被执行并不完全正确。见this answer 来自Haacked:

    两种可能:

    • StackOverflowException
    • ExecutingEngineException

    finally 块不会被执行 当有 StackOverflowException 因为堆栈上没有空间 甚至执行更多代码。它会 当有一个时也不会被调用 ExecutingEngineException,即 非常罕见。

    但是,这两个异常是你无法恢复的异常,所以基本上你的进程无论如何都会退出。

    正如 Mehrdad 所说,可靠的 try/catch/finally 必须使用 Constrained Execution Regions (CER)。 example 由 MSDN 提供:

    [StructLayout(LayoutKind.Sequential)]
    struct MyStruct
    {
        public IntPtr m_outputHandle;
    }
    
    sealed class MySafeHandle : SafeHandle
    {
        // Called by P/Invoke when returning SafeHandles
        public MySafeHandle()
            : base(IntPtr.Zero, true)
        {
        }
    
        public MySafeHandle AllocateHandle()
        {
            // Allocate SafeHandle first to avoid failure later.
            MySafeHandle sh = new MySafeHandle();
    
            RuntimeHelpers.PrepareConstrainedRegions();
            try { }
            finally
            {
                MyStruct myStruct = new MyStruct();
                NativeAllocateHandle(ref myStruct);
                sh.SetHandle(myStruct.m_outputHandle);
            }
    
            return sh;
        }
    }
    

    【讨论】:

      【解决方案6】:

      通常无论是否抛出异常以及是否处理任何异常,都会始终执行 finally 块。

      有几个例外(有关详细信息,请参阅其他答案)。

      【讨论】:

        【解决方案7】:

        最后每次都会发生在 try catch 块中

        【讨论】:

          【解决方案8】:

          不管是否抛出异常,都会执行'Finally'。

          这是关闭任何打开连接的好地方。执行成功或失败,您仍然可以管理连接或打开文件。

          【讨论】:

            【解决方案9】:

            finally 总是被执行。我不依赖于 try 块的工作方式。 如果你必须为 try 和 cath 做一些额外的工作,最好放入 finally 块。所以你可以保证它总是被执行。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-10-03
              • 1970-01-01
              • 1970-01-01
              • 2013-02-23
              • 2018-02-20
              • 2019-01-07
              • 2011-03-28
              相关资源
              最近更新 更多