IDisposable.Dispose在使用块中的exception后永远不会被调用

我从许多这样的来源了解到,如果在Using块中抛出exception,将始终调用IDisposableDispose方法。 那么我有这个代码:

 static class MainEntryPoint { static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException; using (var x = new Disposable()) { throw new Exception("asdfsdf"); } } private static void HandleUnhandledException(Object sender, System.UnhandledExceptionEventArgs e) { Environment.Exit(0); } } class Disposable : IDisposable { public void Dispose() { System.Diagnostics.Debug.Print("I am disposed"); } } 

当抛出未处理的exception时,它退出应用程序。 永远不会调用Dispose方法。 为什么?

Environment.Exit将终止该程序

如果从try或finally块调用Exit,则任何catch块中的代码都不会执行。 如果使用return语句,catch块中的代码会执行。

 using (var x = new Disposable()) { throw new Exception("asdfsdf"); } 

将被转换为

 Disposable x = new Disposable(); try { throw new Exception("asdfsdf"); } finally { if (x != null) x.Dispose(); } 

请注意,如果您已将终结器添加到Disposable ,例如:

 public class Disposable : IDisposable { public void Dispose() { Dispose(true); } protected virtual void Dispose(bool disposing) { Console.WriteLine("I am disposed"); if (disposing) { GC.SuppressFinalize(this); } } ~Disposable() { Dispose(false); } } 

(所以使用“完整” IDisposable模式),然后“通常”将调用终结器(因为终结器有机会在Environment.Exit上运行),并且该方法将调用Dispose(bool disposing) 。 请注意,即使在这里也有可能不会运行终结器,因为它们有一个运行时间限制, 请参阅 。

究竟! 由于在事件处理程序中调用了Environment.Exit(0),因此无法调用Dispose方法中的代码。

尝试删除对Environment.Exit(0)的调用,看看是否调用了Debug.Print()。