我有一个父类和子类,都需要实现IDisposable
。 virtual
(和base.Dispose()
?)来电应该在何处发挥作用?当我只是覆盖Dispose(bool disposing)
调用时,如果我没有明确的IDisposable
函数(只使用继承的函数)而实现Dispose()
,那么我觉得很奇怪,但还有其他所有内容。
我一直在做什么(微不足道):
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);
}
}
答案 0 :(得分:25)
当我刚刚覆盖Dispose(bool disposing)调用时,我觉得很奇怪,我在没有显式Dispose()函数的情况下实现了IDisposable(只使用了继承的函数),但还有其他一切。
这是你不应该关注的事情。
当您继承IDisposable类时,基类已经为您处理了所有“Dispose模式”管道。除了覆盖protected Dispose(bool)
方法之外,你真的应该什么都不做,并追踪你是否已被处置(正确地提升ObjectDisposedException
。)
有关详细信息,请参阅Subclassing from an IDisposable class上的博文。
此外,通常,考虑封装IDisposable类而不是子类化它是个好主意。有时候对IDisposable类进行子类化是合适的,但它们有点罕见。封装通常是更好的选择。
答案 1 :(得分:5)
为什么在不需要时会使事情变得复杂?
由于您没有封装任何非托管资源,因此您不需要完成所有这些操作。而且,您的类是内部的,这表明您可以控制自己程序集中的继承层次结构。
所以,直截了当的方法是:
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();
}
}
即使你确实拥有非托管资源,我也会说你在他们自己的一次性课程中使用encapsulating them要好得多,并且使用它们就像你使用任何其他一次性用品一样;像上面的代码一样直截了当。
答案 2 :(得分:3)
此模式的想法是覆盖虚拟Dispose
方法,必要时调用base.Dispose
。基类负责其余部分,调用虚拟Dispose方法(因此也就是正确的实现)。子类不需要也实现IDisposable
(通过继承来IDisposable
)
答案 3 :(得分:1)
子类应该覆盖虚拟Dispose,执行特定于子类的任何处理,并调用超类'Dispose,然后它将自己完成工作。
编辑:http://davybrion.com/blog/2008/06/disposing-of-the-idisposable-implementation/是我在这种情况下遵循的模式。不是'Disposable'类,而是继承和覆盖。
答案 4 :(得分:0)
我总是转向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成员。另请注意资源的空值检查,因为您不希望在这些块中出现任何异常。
路