请注意,任何 IDisposable 实现都应遵循以下模式(恕我直言)。我根据来自几个优秀的 .NET “神”.NET Framework Design Guidelines 的信息开发了这个模式(请注意,MSDN 出于某种原因不遵循这个!)。 .NET Framework 设计指南由 Krzysztof Cwalina(当时的 CLR 架构师)和 Brad Abrams(我相信当时的 CLR 项目经理)和 Bill Wagner([Effective C#] 和 [More Effective C#]在 Amazon.com 上查找这些:
请注意,除非您的类直接包含(而不是继承)非托管资源,否则您永远不应该实现终结器。一旦你在一个类中实现了一个终结器,即使它从未被调用,它也可以保证为一个额外的集合而存在。它会自动放置在 Finalization Queue(在单个线程上运行)中。此外,一个非常重要的注意事项......在终结器中执行的所有代码(如果您需要实现一个)必须是线程安全和异常安全的!否则会发生糟糕的事情......(即未确定的行为,在异常情况下,致命的不可恢复的应用程序崩溃)。
我整理的模式(并为其编写了一个代码 sn-p)如下:
#region IDisposable implementation
//TODO remember to make this class inherit from IDisposable -> $className$ : IDisposable
// Default initialization for a bool is 'false'
private bool IsDisposed { get; set; }
/// <summary>
/// Implementation of Dispose according to .NET Framework Design Guidelines.
/// </summary>
/// <remarks>Do not make this method virtual.
/// A derived class should not be able to override this method.
/// </remarks>
public void Dispose()
{
Dispose( true );
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
// Always use SuppressFinalize() in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize( this );
}
/// <summary>
/// Overloaded Implementation of Dispose.
/// </summary>
/// <param name="isDisposing"></param>
/// <remarks>
/// <para><list type="bulleted">Dispose(bool isDisposing) executes in two distinct scenarios.
/// <item>If <paramref name="isDisposing"/> equals true, the method has been called directly
/// or indirectly by a user's code. Managed and unmanaged resources
/// can be disposed.</item>
/// <item>If <paramref name="isDisposing"/> equals false, the method has been called by the
/// runtime from inside the finalizer and you should not reference
/// other objects. Only unmanaged resources can be disposed.</item></list></para>
/// </remarks>
protected virtual void Dispose( bool isDisposing )
{
// TODO If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
try
{
if( !this.IsDisposed )
{
if( isDisposing )
{
// TODO Release all managed resources here
$end$
}
// TODO Release all unmanaged resources here
// TODO explicitly set root references to null to expressly tell the GarbageCollector
// that the resources have been disposed of and its ok to release the memory allocated for them.
}
}
finally
{
// explicitly call the base class Dispose implementation
base.Dispose( isDisposing );
this.IsDisposed = true;
}
}
//TODO Uncomment this code if this class will contain members which are UNmanaged
//
///// <summary>Finalizer for $className$</summary>
///// <remarks>This finalizer will run only if the Dispose method does not get called.
///// It gives your base class the opportunity to finalize.
///// DO NOT provide finalizers in types derived from this class.
///// All code executed within a Finalizer MUST be thread-safe!</remarks>
// ~$className$()
// {
// Dispose( false );
// }
#endregion IDisposable implementation
这是在派生类中实现 IDisposable 的代码。请注意,您不需要在派生类的定义中显式列出从 IDisposable 继承的内容。
public DerivedClass : BaseClass, IDisposable (remove the IDisposable because it is inherited from BaseClass)
protected override void Dispose( bool isDisposing )
{
try
{
if ( !this.IsDisposed )
{
if ( isDisposing )
{
// Release all managed resources here
}
}
}
finally
{
// explicitly call the base class Dispose implementation
base.Dispose( isDisposing );
}
}
我已经在我的博客上发布了这个实现:How to Properly Implement the Dispose Pattern