IDisposableを実装する際は以下の要件を満たすために、Dispose Finalizeパターンを適用する。
- Dispose()はマネージリソースとアンマネージリソースの解放処理を行う。
- デストラクタはアンマネージリソースの解放処理を行う。
- Dispose()が呼び出された場合、デストラクタがGCによって呼び出されることのないようにする。
- Dispose()は複数回呼び出されても良いようにする。
- Dispose()、デストラクタでは、例外がスローされないようにする。
- Dispose()が呼び出された後にDispose()以外のパブリックメソッドを呼び出すとObjectDisposedExceptionがスローされるようにする。
Dispose Finalize パターンpublic class Class1 : IDisposable
{
private bool disposed;
public Class1()
{
this.disposed = false;
}
public void Dispose()
{
GC.SuppressFinalize(this);
this.Dispose(true);
}
~Class1()
{
this.Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (this.disposed)
{
return;
}
this.disposed = true;
if (disposing)
{
// マネージリソースの解放処理
}
// アンマネージリソースの解放処理
}
public void Method1()
{
this.ThrowExceptionIfDisposed();
// Method1の処理
}
protected void ThrowExceptionIfDisposed()
{
if (this.disposed)
{
throw new ObjectDisposedException(this.GetType().ToString());
}
}
}
void Dispose(bool disposing)メソッドは、クラスがシールドクラスでない場合は上記のようにプロテクトな仮想メソッドとし、クラスがシールドクラスである場合はプライベートなメソッドとする。
// 追記
ThrowExceptionIfDisposed()メソッドはDispose Finalizeパターンに含まれていないが、このメソッドをプロテクトメソッドとして用意することにより、派生クラスで定義したメソッドでも Dispose済みかどうかを簡単に調べる(というかObjectDisposedExceptionをスローする)ことができる。
// 追追記
Dispose Finalizeパターンを実装するクラスのテンプレートを作成しました。このテンプレートを使えば、Dispose Finalizeパターンを簡単に実装できます。
Dispose Finalizeパターンを実装するクラスのテンプレート
DisposedCheckという名称のメソッドを、ThrowExceptionIfDisposedという名称に変更。
トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/2-2b60e36d