【发布时间】:2013-10-09 20:17:13
【问题描述】:
(Windows API 创建的对象、文件、数据库连接对象、COM 对象等)不在 .NET Framework 的范围内。我们必须明确地清理我们的资源。对于这些类型的对象,.NET Framework 提供了Object.Finalize 方法,可以重写和清理非托管资源的代码...
为什么首选不使用 finalize 进行清理?
用什么合适?
【问题讨论】:
(Windows API 创建的对象、文件、数据库连接对象、COM 对象等)不在 .NET Framework 的范围内。我们必须明确地清理我们的资源。对于这些类型的对象,.NET Framework 提供了Object.Finalize 方法,可以重写和清理非托管资源的代码...
为什么首选不使用 finalize 进行清理?
用什么合适?
【问题讨论】:
首选方法是实现IDisposable 和dispose pattern。终结器是有时间限制的,如果它阻塞太久,GC 将终止终结器 - 这是尽可能避免它的主要原因。
Dispose 只是一个方法调用,没有时间限制。对于调用者忘记调用Dispose(因为它没有被强制执行)作为释放资源的最后尝试的情况,dispose 模式可以选择使用终结器。如果调用了 dispose,该模式还会抑制终结器。
我遇到的需要终结器的唯一有效用途是用于我为第三方应用程序编写的一系列加载项,这些加载项没有引发相关事件以正确管理对象生命周期。我使用终结器来确保我至少尝试过清理东西。除此之外,我从未直接依赖它。
IDisposable 在 C# 中使用 using 关键字来处理。任何实现这个接口的东西都可以这样使用:
using (var myDisposableItem = new MyDisposableItem())
{
} // Dispose will be called here for you.
所以从调用的角度来看,这很简单。
.NET Framework 中有多种类型实现了IDisposable,但没有什么可处理的。我总是建议他们表现得好像他们需要直接处置一样,因为公共合同规定他们有东西要处置,即使实施没有。不要针对实现细节进行编程。
【讨论】:
IDisposable 相提并论,但要回答如果您在using 语句中发生异常会发生什么的问题,@987654331 @ 方法会被调用,因为编译器会为它生成一个try-finally。
using (existingObject as IDisposable) { ... } 来捕获派生实现为 IDisposable 的所有情况,但父级的文档(和实现)没有提及 IDisposable。