当父类也实现IDisposable时,在子类上实现IDisposable

我有一个父类和子类,都需要实现IDisposablevirtual (和base.Dispose() ?)调用应该在哪里发挥作用? 当我只是重写Dispose(bool disposing)调用时,我觉得很奇怪,我没有显式的Dispose()函数(只使用inheritance的)实现IDisposable ,但是还有其他的东西。

我一直在做什么(微不足道):

 internal class FooBase : IDisposable { Socket baseSocket; private void SendNormalShutdown() { } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { SendNormalShutdown(); } baseSocket.Close(); } } ~FooBase() { Dispose(false); } } internal class Foo : FooBase, IDisposable { Socket extraSocket; private bool _disposed = false; protected override void Dispose(bool disposing) { if (!_disposed) { extraSocket.Close(); } base.Dispose(disposing); } ~Foo() { Dispose(false); } } 

当我只是重写Dispose(bool disposing)调用时,我觉得很奇怪,我没有显式的Dispose()函数(只使用inheritance的)实现IDisposable,但是还有其他的东西。

这是你不应该关心的事情。

当您inheritanceIDisposable类时,基类已经为您处理了所有“Dispose模式”管道。 除了覆盖protected Dispose(bool)方法之外,你真的应该什么都不做,并跟踪你是否已经处理掉(以正确引发ObjectDisposedException 。)

有关详细信息,请参阅我在IDisposable类中进行子类化的博客文章。


此外,通常,考虑封装IDisposable类而不是子类化它是个好主意。 有时候对IDisposable类进行子类化是合适的,但它们有点罕见。 封装通常是更好的选择。

当你不需要时为什么复杂化?

由于您没有封装任何非托管资源,因此您不需要完成所有这些操作。 而且,您的类是内部的,这表明您可以控制自己程序集中的inheritance层次结构。

所以,直截了当的方法是:

 internal class FooBase : IDisposable { Socket baseSocket; private void SendNormalShutdown() { // ... } private bool _disposed = false; public virtual void Dispose() { if (!_disposed) { SendNormalShutdown(); baseSocket.Close(); _disposed = true; } } } internal class Foo : FooBase { Socket extraSocket; private bool _disposed = false; public override void Dispose() { if (!_disposed) { extraSocket.Close(); _disposed = true; } base.Dispose(); } } 

即使你确实拥有非托管资源,我也会说你最好将它们封装在自己的一次性类中,然后使用它们,就像你使用任何其他一次性用品一样; 像上面的代码一样直截了当。

这种模式的想法是覆盖虚拟Dispose方法,必要时调用base.Dispose 。 基类负责其余部分,调用虚拟Dispose方法(因此也是正确的实现)。 子类不需要也实现IDisposable (它可以通过inheritanceIDisposable

子类应覆盖虚拟Dispose,执行特定于子类的任何处理,并调用超类’Dispose,而Dispose又将自己完成工作。

编辑: http : //davybrion.com/blog/2008/06/disposing-of-the-idisposable-implementation/是我在这种情况下遵循的模式。 不是’Disposable’类,而是inheritance和覆盖。

我总是转向Joe Duffy对这种模式的深入研究。 对我来说,他的版本是福音书。

http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/

首先要记住的是,大部分时间都不需要终结器。 它用于清除您直接持有本机资源的非托管资源,即只有没有自己的终结器的资源。

这是基类子类对的示例。

 // Base class #region IDisposable Members private bool _isDisposed; public void Dispose() { this.Dispose(true); // GC.SuppressFinalize(this); // Call after Dispose; only use if there is a finalizer. } protected virtual void Dispose(bool isDisposing) { if (!_isDisposed) { if (isDisposing) { // Clear down managed resources. if (this.Database != null) this.Database.Dispose(); } _isDisposed = true; } } #endregion // Subclass #region IDisposable Members private bool _isDisposed; protected override void Dispose(bool isDisposing) { if (!_isDisposed) { if (isDisposing) { // Clear down managed resources. if (this.Resource != null) this.Resource.Dispose(); } _isDisposed = true; } base.Dispose(isDisposing); } #endregion 

请注意,子类具有自己的_isDisposed成员。 还要注意资源的空值检查,因为您不希望在这些块中出现任何exception。

卢克