当父类也实现IDisposable时,在子类上实现IDisposable
我有一个父类和子类,都需要实现IDisposable
。 virtual
(和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。
卢克