嗯,你在这里画的画有点过于乐观了。终结器也不能保证在 .NET 中运行。典型的事故是终结器在终结器线程上抛出异常或超时(2 秒)。
当 Microsoft 决定在 SQL Server 中提供 .NET 托管支持时,这是一个问题。重新启动应用程序以解决资源泄漏的应用程序不被认为是可行的解决方法。.NET 2.0 获得了通过从 CriticalFinalizerObject 类派生的关键终结器。此类的终结器必须遵守受约束执行区域 (CER) 的规则,本质上是抑制异常的代码区域。您可以在 CER 中做的事情非常有限。
回到您最初的问题,终结器是释放内存以外的操作系统资源所必需的。垃圾收集器很好地管理内存,但不会做任何事情来释放笔、画笔、文件、套接字、窗口、管道等。当一个对象使用这样的资源时,它必须确保在完成后释放资源它。终结器确保发生这种情况,即使程序忘记这样做。您几乎从不自己编写带有终结器的类,操作资源由框架中的类包装。
.NET 框架还具有一种编程模式,可确保尽早释放此类资源,以便资源在终结器运行之前不会徘徊。所有具有终结器的类也实现 IDisposable.Dispose() 方法,允许您的代码显式释放资源。.NET 程序员经常忘记这一点,但这通常不会导致问题,因为终结器确保它最终会完成。许多 .NET 程序员已经失去了几个小时的睡眠,担心是否所有的 Dispose() 调用都得到了处理,并且论坛上已经启动了大量关于它的线程。Java 的人一定更快乐。
跟进您的评论:终结器线程中的异常和超时是您不必担心的。首先,如果您发现自己正在编写终结器,请深呼吸并问自己是否走在正确的道路上。终结器用于框架类,您应该使用这样的类来使用操作资源,您将免费获得该类中内置的终结器。一直到 SafeHandle 类,它们都有一个关键的终结器。
其次,终结器线程故障是严重的程序故障。类似于出现 OutOfMemory 异常或绊倒电源线并拔下机器。除了修复代码中的错误或重新布线之外,您无能为力。对 Microsoft 来说,设计关键的终结器很重要,他们不能依赖所有为 SQL Server 编写 .NET 代码的程序员来正确地编写代码。如果你自己摸索终结者,那么就没有这种责任,你会接到客户的电话,而不是微软。