- 一个类只管理成员。
- 一些成员实现了
IDisposable
接口。 - 该类是密封的 - 无法从中派生并添加非托管资源。
- 对象在
using
语句内使用 - 即在完成时调用Dispose()
。
这个类有3种可能的IDisposable
实现:
- 最小化的
Dispose
方法,它会调用IDisposable
成员上的Dispose()
- 没有终结器。 - 标准的
IDisposable
实现,带有终结器,但Dispose()
中缺少通常的GC.SuppressFinalize(this)
调用。 - 完整的标准
IDisposable
实现,带有终结器(并在Dispose()
中调用GC.SuppressFinalize(this)
)。
以下说法是否正确?我理解得对吗?
- 情况A.比B.和C.略微开销小,因为该对象没有终结器,所以不会进入GC的终结器队列 - 因此GC可以在收集时尽早清除该对象 - 没有开销。
- 情况B.该对象有终结器,因此将进入GC的终结器队列,并且将调用终结器(因为它没有被抑制) - 终结器调用
Dispose
,但什么也不做,因为已经被调用过了。这会产生小的开销,即对象在终结器队列中以及终结器调用的非常小的开销。 - 情况C.该对象具有终结器,因此仍将进入GC的终结器队列。由于已调用
Dispose
和SuppressFinalize
,因此终结器不会运行。这种情况仍然会产生对象进入终结器队列的小开销,但实际上不会运行终结器。
这里的关键点是很容易认为“通过调用SuppressFinalize
来避免终结器开销”,但我认为(并希望澄清)这是不正确的。对象进入终结器队列的开销仍然会发生 - 所有你要做的就是避免实际的终结器调用 - 在常见情况下,这只是“我已经被处理了,什么也不做”。
注意:这里的“完整的标准IDisposable
实现”是指旨在涵盖非托管和托管资源情况的标准实现(请注意,这里我们只有托管对象成员)。
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed;
protected virtual void Dispose(bool disposing) {
if (_disposed)
return;
if (disposing) {
// dispose managed members...
}
_disposed = true;
}
~AXCProcessingInputs() {
Dispose(false);
}
return
语句后面添加一些代码页。如果他问,就说这没有任何额外开销,因为这段代码永远不会运行。 - C.Evenhuis