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块不会执行。
- Environment.FailFast
- 无法捉摸的怀疑
- 电源(检测)失败
finally
永远执行是不完全正确的。 从Haacked看这个答案 :
两种可能性:
StackOverflowException
ExecutingEngineException
当有StackOverflowException时,finally块不会被执行,因为堆栈上没有空间来执行更多的代码。 当ExecutingEngineExceptionexception时,它也不会被调用,这是非常罕见的。
实际上,对于任何types的asynchronousexception(如StackOverflowException
, OutOfMemoryException
, ThreadAbortException
),不保证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块如何退出。
简单的回答是的。 但是这个规则有一些“例外”。