管理されていないリソースを持つクラスがあります。私のクラスはIDisposable
インターフェイスを実装し、Dispose()
メソッドでアンマネージリソースを解放します。 Dispose()
メソッドを呼び出す必要がありますか、それとも何らかの方法で自動的に呼び出されますか?ガベージコレクターはそれを呼び出しますか?
Dispose()
は自動的に呼び出されません。 finalizerがある場合、自動的に呼び出されます。 IDisposable
を実装すると、クラスのユーザーがガベージコレクターを待つのではなく、リソースを早期に解放できます。
クライアントにとって望ましい方法は、例外がある場合でもDispose()
の自動呼び出しを処理するusing
ステートメントを使用することです。
IDisposable
の適切な実装は次のとおりです。
_class MyClass : IDisposable
{
private bool disposed = false;
void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// Manual release of managed resources.
}
// Release unmanaged resources.
disposed = true;
}
}
~MyClass() { Dispose(false); }
}
_
クラスのユーザーがDispose()
を呼び出すと、クリーンアップが直接行われます。オブジェクトがガベージコレクターによってキャッチされると、Dispose(false)
を呼び出してクリーンアップを実行します。ファイナライザー(_~MyClass
_メソッド)から呼び出された場合、マネージ参照は無効になる可能性があるため、アンマネージリソースのみを解放できることに注意してください。
using
ステートメントでオブジェクトをインスタンス化すると、コードがusing
ブロックを終了するときにDispose()が呼び出されます
using(var myObject = new MyDisposableObject())
{
blah();
} // Dispose() is called here (or whenever the code exits the block)
using
を使用しない場合、Dispose()を明示的に呼び出してオブジェクトを破棄するのは(呼び出し元のコード)次第です。
また、あなた(MyObjectの実装者)は、呼び出し元がDispose()を呼び出さない場合に備えて、ファイナライザーのサポートを追加できます。詳細 こちら 。
リソースを正しく破棄するには、IDisposable
を実装し、デストラクタ(ファイナライザ)でDispose
を呼び出す必要があります。
class Foo : IDisposable
{
private bool m_disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Foo()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (!m_disposed)
{
if (disposing)
{
//release managed resources
}
//release unmanaged resources
m_disposed = true;
}
}
}
willこのメソッドを手動で呼び出す必要があります。
using(var myclass = new MyClass())
{
// do something with myclass
}
// now 'myclass'is Disposed