另一个面试问题是期待一个真/假答案,我不太确定。
答案 0 :(得分:27)
finally
大部分时间执行。这几乎是所有情况。例如,如果在线程上抛出异步异常(如StackOverflowException
,OutOfMemoryException
,ThreadAbortException
),则无法保证执行finally
。这就是为编写高可靠性代码而存在constrained execution regions的原因。
对于面试目的,我希望这个问题的答案是 false (我不保证任何事情!面试官可能不会自己知道!)。
答案 1 :(得分:8)
通常,finally
块保证执行。
但是,少数情况会强制CLR在发生错误时关闭。在这些情况下,finally
块不会运行。
一个这样的例子是存在StackOverflow异常。
E.g。在下面的代码中,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
之前终止。
我承认这些例子非常人为,但它们只是为了说明这一点。
幸运的是,这种情况经常发生。
答案 2 :(得分:7)
直接来自MSDN:
finally块非常有用 清理分配的任何资源 试块。总是控制 无论如何传递给finally块 如何退出try块。
而catch用于处理 声明中出现的异常 块,最后是用来保证一个 语句代码块执行 不管前面的尝试如何 阻止退出。
http://msdn.microsoft.com/en-us/library/zwc8s4fz(VS.71,loband).aspx
答案 3 :(得分:4)
是的,最后总是被执行。
答案 4 :(得分:3)
最终将永远执行并不完全正确。请参阅this answer中的Haacked:
两种可能性:
StackOverflowException
ExecutingEngineException
不会执行finally块 当有StackOverflowException时 因为堆栈上没有空间 甚至执行更多的代码。它会 当有一个时也不会被叫 ExecutingEngineException,这是 非常罕见。
但是,这两个例外情况是您无法恢复的例外情况,所以基本上您的流程无论如何都会退出。
如Mehrdad所述,可靠的try / catch / finally必须使用Constrained Execution Regions (CER)。 MSDN提供example:
[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;
}
}
答案 5 :(得分:1)
通常无论是否抛出异常以及是否处理任何异常,都始终执行finally块。
有几个例外(有关详细信息,请参阅其他答案)。
答案 6 :(得分:0)
'finally'都会被执行。
这是关闭任何开放连接的好地方。执行成功或失败,您仍然可以管理您的连接或打开文件。
答案 7 :(得分:-1)
最后,每次尝试捕获块
都会发生答案 8 :(得分:-1)
最后保证在任何情况下都会执行阻止。
答案 9 :(得分:-1)
最后总是执行。我不依赖于try块的工作原理。 如果你必须为try和cath做一些额外的工作,最好放入finally块。所以你可以保证它总是被执行。