C#“终于”阻止总是执行?

可能重复:
如果我在Try块中返回一个值,将会在finally语句中编写代码?

考虑下面的代码C#代码。 “finally”块是否执行?

public void DoesThisExecute() { string ext = "xlsx"; string message = string.Empty; try { switch (ext) { case "xls": message = "Great choice!"; break; case "csv": message = "Better choice!"; break; case "exe": message = "Do not try to break me!"; break; default: message = "You will not win!"; return; } } catch (Exception) { // Handle an exception. } finally { MessageBox.Show(message); } } 

哈,写完这些之后,我意识到我可以在Visual Studio中自己完成testing。 不过,请随时回答!

不,不是的。 只要应用程序仍在运行,它将始终执行(除了FastFailexception, MSDN链接 ,如其他人所述)。 它将在退出块的try / catch部分时执行。

如果应用程序崩溃,它将不会执行:通过杀死进程命令等杀死这是非常重要的,因为如果你写代码,绝对期望它运行,就像手动回滚,否则将自动提交,你可以运行一个应用程序在这种情况发生之前中止的场景。 老实说,这是一种外部的情况,但在这种情况下要注意这一点很重要。

从msdn C#规范的try语句。

当控制离开一个try语句时,finally块的语句总是被执行。 无论是执行break,continue,goto还是return语句,还是作为从try语句的try语句中传出exception的结果,控制转移是否由于正常执行而发生。

来源链接:

http://msdn.microsoft.com/en-us/library/aa664733(v=VS.71).aspx

有些情况下finally块不会执行。

  1. Environment.FailFast
  2. 无法捉摸的怀疑
  3. 电源(检测)失败

finally永远执行是不完全正确的。 从Haacked看这个答案 :

两种可能性:

  • StackOverflowException
  • ExecutingEngineException

当有StackOverflowException时,finally块不会被执行,因为堆栈上没有空间来执行更多的代码。 当ExecutingEngineExceptionexception时,它也不会被调用,这是非常罕见的。

实际上,对于任何types的asynchronousexception(如StackOverflowExceptionOutOfMemoryExceptionThreadAbortException ),不保证finally块的执行。

但是,这些例外情况是您通常无法恢复的例外情况,在大多数情况下,您的stream程仍将退出。

事实上,至less还有另外一个情况是Brian Rasmussen在一个现在被删除的问题中finally没有被执行:

我知道的另一种情况是如果一个终结器抛出一个exception。 在这种情况下,该过程也将立即终止,因此担保不适用。

下面的代码说明了这个问题

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

一个可靠的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; } } 

一个很好的信息来源是以下文章:

可靠性最佳实践

从MSDN 尝试最后(C#参考)

finally块用于清理try块中分配的任何资源,以及运行即使有exception也必须执行的任何代码。 无论try块如何退出,控制总是传递给finally块

finally块将在这些行之间运行:

 message = "You will not win!"; return; 

是的, finally总是执行,现在finally代码块中的代码是否会导致exception是一个不同的故事。

正确的答案是肯定的。

尝试debugging你的程序,并把一个断点,看着控制仍然击中finally块。

不,不。

只有一个方法,那就是Environment.FailFast() 。 请参阅http://msdn.microsoft.com/de-de/library/ms131100.aspx 。 在其他情况下,保证终结器得到执行;-)

FailFast方法将消息string写入Windows应用程序事件日志,创build应用程序的转储,然后终止当前进程。 邮件string也包含在向Microsoft报告的错误中。

使用FailFast方法而不是Exit方法来终止你的应用程序,如果你的应用程序的状态被破坏无法修复,执行你的应用程序的try / finally块和终结器会损坏程序资源。

是的,正常情况下(正如其他人指出的那样)。

finally块用于清理try块中分配的任何资源,以及运行即使有exception也必须执行的任何代码。 无论try块如何退出,控制总是传递给finally块。

而catch用于处理发生在语句块中的exception,最后用来保证执行语句代码块,而不pipe前面的try块如何退出。

http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx

简单的回答是的。 但是这个规则有一些“例外”。