IDisposable GC.SuppressFinalize(this)の場所
-
03-07-2019 - |
質問
コードにデフォルトのIDisposable実装テンプレート(パターン)を使用しています。
スニペット:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool isDisposing)
{
if (!this.disposed)
{
if (isDisposing)
{
//cleanup managed resources
}
//cleanup unmanaged resources
this.disposed = true;
}
}
私の質問:なぜ" GC.SuppressFinalize(this)"が呼び出されるのですか?パブリックメソッドを破棄しますか? 「GC.SuppressFinalize(this)」を配置します; " if(isDisposing)"マネージリソースを破棄した後、保護されたメソッドのセクション。
これに似ています:
protected virtual void Dispose(bool isDisposing)
{
if (!this.disposed)
{
if (isDisposing)
{
//cleanup managed resources
GC.SuppressFinalize(this);
}
//cleanup unmanaged resources
this.disposed = true;
}
}
解決
テンプレートデザインパターンの明確なケースだと思います。
抽象クラスは、必要なすべての重要/必要なタスク(ここではGC.SuppressFinalize(this))を処理し、派生クラスがコードの一部のみをオーバーライドできるように設計されています。
ここには2つのケースがあります:
スニペット1、SuppressFinalize、破棄
スニペット2、SuppressFinalize、Dispose(true)で
ここで、スニペット1は、GC.SuppressFinalizeが常に実行されるようにします。スニペット2では、GC.SuppressFinalizeの実行は派生クラスに委ねられます。
したがって、GC.SuppressFinalizeをDisposeメソッドに配置することにより、クラスの設計者は、派生クラスによって記述されたコードに関係なく、GC.SuppressFinalizeが必ず実行されるようにします。
これは、Dispose(true)ではなくDisposeでSuppressFinalizeを記述することの利点にすぎません。
他のヒント
Dispose(bool isDisposing)
メソッドは、 IDisposable
インターフェース。
通常、Dispose(true)を呼び出します。 = "noreferrer"> Dispose
メソッドを使用し、オブジェクトがまだ実行されていない場合のフォールバックとして、ファイナライザから Dispose(false)
を呼び出します
SuppressFinalize
は、おそらく Dispose
が呼び出されたときにすべてのクリーンアップが行われたため、オブジェクトのファイナライザを呼び出す必要がないことをGCに伝えます。
クラスにファイナライザがない場合、抑制するファイナライザがないため、 SuppressFinalize
を呼び出す必要はありません!
Joe Duffyには、素晴らしい廃棄、ファイナライズ、ガベージコレクションなどのガイドラインがあります。 。
どちらのレイアウトも選択できたと思いますが、おそらく「この方法ですべての割り当て解除コードを置く」ことを強調したかったのでしょう。保護されたDisposeメソッドにあるため、他の処理(ファイナライズの抑制)の他のアーティファクトを他の場所に配置します。
また、派生クラスに、保護されたDisposeメソッドを呼び出す別の理由があるが、ファイナライズが発生することを望んでいたとします(想像される理由が何であれ、私は知りません)。
原因.Disposeは、マネージコード(コード)がオブジェクトを破棄することで、ファイナライズをオプトアウトする場合です。通常、ファイナライザを介してDispose(bool disposing)への別のルートを作成しますが、ファイナライザがこの呼び出しを実行しても意味がありません。
アイデアは、クリーンアップコードを1回だけ呼び出す必要があるということです。ただし、 Dispose
メソッドとオブジェクトファイナライザの2つのエントリポイントがあります。 Dispose
が呼び出されると、クリーンアップコードが1回だけ呼び出されるように、ファイナライズをオプトアウトします。 こちらのコードで、より適切に説明できます。
引用:
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources itself, but leave the other methods
// exactly as they are.