在 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
In C# will the Finally block be executed in a try, catch, finally if an unhandled exception is thrown?
提问by Gais
Another interview question which was expecting a true / false answer and I wasn't too sure.
另一个面试问题,期待一个真/假的答案,我不太确定。
Duplicate
复制
采纳答案by Mehrdad Afshari
finally
is 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, finally
execution 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 finally
block is guaranteed to execute.
通常finally
保证块执行。
However, a few cases forces the CLR to shutdown in case of an error. In those cases, the finally
block is not run.
但是,少数情况下会强制 CLR 在出现错误时关闭。在这些情况下,finally
块不会运行。
One such example is in the presence of a StackOverflow exception.
一个这样的例子是存在 StackOverflow 异常。
E.g. in the code below the finally
block 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 catch
and 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 块。所以你可以保证它总是被执行。