C# Language
IDisposableインターフェイス
サーチ…
備考
IDisposable
を実装しているクラスのクライアントは、オブジェクトの使用が終了したらDispose
メソッドを呼び出すようにしています。 CLRには、呼び出すDispose
メソッドのオブジェクトを直接検索するものは何もありません。オブジェクトに管理されたリソースのみが含まれている場合は、ファイナライザを実装する必要はありません。独自の
Dispose
メソッドを実装するときにクラスが使用するすべてのオブジェクトに対してDispose
を呼び出すようにしてください。理想的には一度だけ呼び出す必要がありますが、クラスを
Dispose
への複数の呼び出しに対して安全にすることをお勧めします。これは、クラスにprivate bool
変数を追加し、Dispose
メソッドが実行されたときに値をtrue
に設定することでtrue
できます。
管理対象リソースのみを含むクラス
管理リソースとは、ランタイムのガベージコレクタが認識し管理しているリソースのことです。 BCLには、管理されていないリソースのラッパークラスであるSqlConnection
など、多数のクラスが用意されています。これらのクラスは既にIDisposable
インターフェイスを実装しています。コードを実行すると、そのコードをクリーンアップすることができます。
クラスにマネージリソースのみが含まれている場合は、ファイナライザを実装する必要はありません。
public class ObjectWithManagedResourcesOnly : IDisposable
{
private SqlConnection sqlConnection = new SqlConnection();
public void Dispose()
{
sqlConnection.Dispose();
}
}
管理リソースと非管理リソースを持つクラス
ファイナライズでは管理対象リソースを無視することが重要です。ファイナライザは別のスレッド上で動作します。ファイナライザが実行されるまでに管理オブジェクトが存在しなくなる可能性があります。保護されたDispose(bool)
メソッドの実装は、管理されたリソースがファイナライザから呼び出されたDispose
メソッドを持たないようにするための一般的な方法です。
public class ManagedAndUnmanagedObject : IDisposable
{
private SqlConnection sqlConnection = new SqlConnection();
private UnmanagedHandle unmanagedHandle = Win32.SomeUnmanagedResource();
private bool disposed;
public void Dispose()
{
Dispose(true); // client called dispose
GC.SuppressFinalize(this); // tell the GC to not execute the Finalizer
}
protected virtual void Dispose(bool disposeManaged)
{
if (!disposed)
{
if (disposeManaged)
{
if (sqlConnection != null)
{
sqlConnection.Dispose();
}
}
unmanagedHandle.Release();
disposed = true;
}
}
~ManagedAndUnmanagedObject()
{
Dispose(false);
}
}
IDisposable、Dispose
.NET Frameworkは、ティアダウンメソッドを必要とするタイプのインターフェイスを定義します。
public interface IDisposable
{
void Dispose();
}
Dispose()
は主に、アンマネージ参照などのリソースのクリーンアップに使用されます。ただし、他のリソースを管理していても強制的に廃棄すると便利です。 GCが最終的にデータベース接続をクリーンアップするのを待つのではなく、自分のDispose()
実装で完了したことを確認することができます。
public void Dispose()
{
if (null != this.CurrentDatabaseConnection)
{
this.CurrentDatabaseConnection.Dispose();
this.CurrentDatabaseConnection = null;
}
}
管理されていないポインタやwin32リソースなどのアンマネージリソースに直接アクセスする必要がある場合は、 SafeHandle
を継承するクラスを作成し、そのクラスの規約/ツールを使用します。
管理されたリソースを持つ継承クラス
IDisposable
を実装するクラスを作成してから、管理されたリソースも含むクラスを生成することは、かなり一般的です。 Dispose
メソッドをvirtual
キーワードでマークして、クライアントが所有するリソースをすべてクリーンアップできるようにすることをお勧めします。
public class Parent : IDisposable
{
private ManagedResource parentManagedResource = new ManagedResource();
public virtual void Dispose()
{
if (parentManagedResource != null)
{
parentManagedResource.Dispose();
}
}
}
public class Child : Parent
{
private ManagedResource childManagedResource = new ManagedResource();
public override void Dispose()
{
if (childManagedResource != null)
{
childManagedResource.Dispose();
}
//clean up the parent's resources
base.Dispose();
}
}
キーワードを使用して
オブジェクトがIDisposable
インターフェイスを実装するとき、それはusing
構文で作成することができます:
using (var foo = new Foo())
{
// do foo stuff
} // when it reaches here foo.Dispose() will get called
public class Foo : IDisposable
{
public void Dispose()
{
Console.WriteLine("dispose called");
}
}
try/finally
ブロックにsyntatic sugarをusing
ます。上記の使用法は、おおよそ次のように解釈されます。
{
var foo = new Foo();
try
{
// do foo stuff
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}