ファイナライザは、フォールバックとして使用されています。通常は、Dispose()
メソッドが呼び出され、ファイナライザの接続を削除し、ガベージコレクタが簡単に削除できる通常の管理オブジェクトにオブジェクトを変換します。
MSDNのクリーンアップする管理対象リソースとアンマネージリソースを持つクラスの例を次に示します。
disposing
がtrueの場合にのみ管理対象リソースがクリーンアップされますが、アンマネージリソースは常にクリーンアップされます。
public class MyResource: IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private Component component = new Component();
// Track whether Dispose has been called.
private bool disposed = false;
// The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
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.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing 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.
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
// Note disposing has been done.
disposed = true;
}
}
// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
しかし、あなたがアンマネージドリソースを持っていなければ 'Dispose(false)'はまったく何もしないので、ファイナライザも 'Dispose(bool)'も必要ないことに注意してください。私は、標準パターンは、ほとんど発生しないユースケースに対応するために過度に複雑であると感じています。ここで私が大好きなのは、http://nitoprograms.blogspot.com/2009/08/how-to-implement-idisposable-and.html –
@romkyns "[IDisposable]の主な用途は、アンマネージドリソースを解放することです。 (http://msdn.microsoft.com/en-us/library/System.IDisposable.aspx)IDisposableを実装する標準的な方法は、管理されていないリソースを持たない場合に必要な以上に驚くことではありません。 「ほとんど発生しないユースケース」が何を意味するのかよく分かりません。管理対象リソースとアンマネージリソースを混在させることはあいまいなユースケースではありません。 –
それは、ファイナライザが何もしていない(管理されていないリソースがないので)なら、あなたはそれを必要としないと私は同意します。ほとんどのパターン(ほとんどのもののように、私が推測する)のように、それは理にかなっているところで使うのが理にかなっています。 ;) –