在 C# 中,如果抛出未处理的异常,是否会在 try、catch、finally 中执行 finally 块?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/833946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:29:54  来源:igfitidea点击:

In C# will the Finally block be executed in a try, catch, finally if an unhandled exception is thrown?

c#.netfinally

采纳答案by Mehrdad Afshari

finallyis executed most of the time. It's almost all cases. For instance, if an async exception (like StackOverflowException, OutOfMemoryException, ThreadAbortException) is thrown on the thread, finallyexecution is not guaranteed. This is why constrained execution regionsexist for writing highly reliable code.

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

For interview purposes, I expect the answer to this question to be false(I won't guarantee anything! The interviewer might not know this herself!).

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

回答by Brian

Yes, finally is always executed.

是的, finally 总是被执行。

回答by ChrisF

Generally the finally block is always executed regardless of whether an exception is thrown or not and whether any exception is handled or not.

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

There are a couple of exceptions (see other answers for more details).

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

回答by fluf

Finally will happen everytime for that try catch block

最后每次都会发生那个 try catch 块

回答by Hemant

Finally block is guaranteed to be executed in any case.

最后块保证在任何情况下都被执行。

回答by John T

Straight from MSDN:

直接来自 MSDN:

The finally block is useful for cleaning up any resources allocated in the try block. Control is always passed to the finally block regardless of how the try block exits.

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.

finally 块可用于清理在 try 块中分配的任何资源。不管 try 块如何退出,控制总是传递给 finally 块。

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

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

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

回答by MoSlo

'Finally' is executed regardless of whether an exception is thrown or not.

无论是否抛出异常,“最终”都会执行。

Its a good place to close any open connections. Successful or failed execution, you can still manage your connections or open files.

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

回答by Dirk Vollmar

It is not totally true that finally will always be executed. See this answerfrom Haacked:

finally 总是会被执行并不完全正确。从Haacked看到这个答案

Two possibilities:

  • StackOverflowException
  • ExecutingEngineException

The finally block will not be executed when there's a StackOverflowException since there's no room on the stack to even execute any more code. It will also not be called when there's an ExecutingEngineException, which is very rare.

两种可能:

  • StackOverflowException
  • ExecutingEngineException

当出现 StackOverflowException 时,finally 块将不会被执行,因为堆栈上没有空间来执行更多代码。当出现 ExecutingEngineException 时也不会调用它,这种情况非常罕见。

However, these two exceptions are exception you cannot recover from, so basically your process will exit anyway.

但是,这两个异常是您无法从中恢复的异常,因此基本上您的进程无论如何都会退出。

As mentioned by Mehrdad, a reliable try/catch/finally will have to use Constrained Execution Regions (CER). An exampleis provided by MSDN:

正如 Mehrdad 所提到的,可靠的 try/catch/finally 必须使用受限执行区域 (CER)。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;
    }
}

回答by Brian Rasmussen

Generally the finallyblock is guaranteed to execute.

通常finally保证块执行。

However, a few cases forces the CLR to shutdown in case of an error. In those cases, the finallyblock is not run.

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

One such example is in the presence of a StackOverflow exception.

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

E.g. in the code below the finallyblock is not executed.

例如,在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);
}

The other case I am aware of is if a finalizer throws an exception. In that case the process is terminated immediately as well, and thus the guarantee doesn't apply.

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

The code below illustrates the problem

下面的代码说明了问题

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

In both cases the process terminates before both catchand finally.

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

I'll admit that the examples are very contrived, but they are just made to illustrate the point.

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

Fortunately neither happens very often.

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

回答by Sauron

Finally is always executed. I not depends on how the try block works. If u have to do some extra work for both try and cath, it is better to put in finally block. So you can gurantee that it is always executed.

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