が独自のクラスである場合Base
は、このアンチパターンを実装しないでください。
2つ折りのdispose(disposedがtrueの場合は1つ、falseの場合は1つ)は、クラスに破棄する必要のあるマネージリソース(たとえば、独自に呼び出されるStreamオブジェクトDispose
)とクリーンアップする必要のあるアンマネージリソースの両方が含まれる場合に使用されます-上。
これは悪い考えです。代わりに、すべてのクラスを1つまたは2つのカテゴリに当てはめてください。
A.管理されていないリソースのみを持つクラス。理想的には、クラスごとに1つだけです。
public sealed class HandlesUnmanaged : IDisposable
{
private IntPtr _someUnmanagedHandleOfSomeKind;
public string DoSomething(string someParam)
{
// your useful code goes here;
// make it thin, non-virtual and likely to be inlined
// if you need to extend functionality, but it in a
// containing Disposable class, not a derived class.
}
private void CleanUp()
{
//your code that cleans-up someUnmanagedHandleOfSomeKind goes here
}
public void Dispose()
{
CleanUp();
GC.SuppressFinalize(this);//finaliser not needed now.
}
~HandlesUnmanaged()//not called if already disposed
{
CleanUp();
}
}
理想的には、このようなクラスは必要ありませんが、それを使用SafeHandle
してください。
B.廃棄する必要のある1つ以上の管理対象リソースを持つクラス:
public class NoUnmanaged : IDisposable
{
private HandlesUnmanaged _likeAbove;
private Stream _anExampleDisposableClass;
public virtual void Dispose()
{
_likeAbove.Dispose();
_anExampleDisposableClass.Dispose();
}
/* Note no finaliser, if Dispose isn't called, then _likeAbove's
finaliser will be called anyway. All a finaliser here would do is
slow things up and possibly introduce bugs.
*/
}
public class DerivedNoUnManaged : NoUnmanaged
{
Stream _weMayOrMayNotHaveAnotherDisposableMember;
public override void Dispose()
{
//note we only need this because we have
//another disposable member. If not, we'd just inherit
//all we need.
base.Dispose();
weMayOrMayNotHaveAnotherDisposableMember.Dispose();
}
}
Dispose()
全体として、前者の呼び出しを除いて、ファイナライザーとファイナライザーで同じことを行う単純な非管理所有クラスがあるか、または、以下を含むすべてを破棄する必要GC.SuppressFinalize
がある単純な非管理所有クラスがあります。必要に応じDispose()
て電話をかけ、base.Dispose()
ファイナライザーはありません。同じクラス内でロジックを2つのタイプに分割する必要はありません。ファイナライザーがファイナライズされたものを呼び出したり、必要以上にファイナライズキューに入れたりするリスクはありません。
そして理想的には、最初のタイプをまったく実行しないことです。ちょうど2番目のタイプ。
他のパーティのクラスから継承することによって強制された場合は、次のようにします。
public MyClass : Base
{
Stream _forExample;
public override void Dispose(bool disposing)
{
if(disposing)
{
_forExample.Dispose();
}
base.Dispose(disposing);
}
}
disposing == false
管理されていないリソースが混在していないため、自分でケースを処理しないでください。