0

このMSDNページの最初

標準のDisposeパターンがあります。また、保護されたメソッドのパラメーターとしてブール値があり、Dispose管理対象リソースが既に手動で解放されているかどうかをGCに通知するため、GCはそれらを気にする必要がありません。

if (disposing) {}ここで問題は、ブロック内で正確に何をすべきかということです。通常、GCは管理対象リソースをクリーンアップするため、特別なことをする必要はありません。しかし、このブロック内では、管理対象リソースを明示的にクリーンアップする必要があるため、オブジェクト内のすべてのフィールドなどをに設定するだけでよいのnullでしょうか。

第二に、その言語でデストラクタ(またはファイナライザーと呼ばれるもの)を1つだけ持つ方が良いのではないでしょうか。次に、GCの設計で、ガベージコレクションが不要になるようにデストラクタがすでに呼び出されているかどうか、またはデストラクタがまだ呼び出されておらず、GCがクリーンアップする必要があるかどうかを判断します。Disposeパターンは非常に複雑で、どの関数で何をクリーンアップするか、派生クラスでどのようにクリーンアップするかについて非常に混乱しています。また、サインルデストラクタ設計を使用することにより、GCは、まだクリーンアップされていないときにクリーンアップするだけで、すでにクリーンアップされているときはクリーンアップしません。

ご挨拶

PS:では、これもオブジェクトをクリーンアップするための優れたシンプルなパターンですか?

class Foo
{
    bool unmanagedDisposed = false;
    void Dispose() {/*clean up unmanaged resources*/ unmanagedDisposed = true;}
    ~Foo() {if (!unmanagedDisposed) Dispose();}
}

したがって、プログラマーが呼び出しを知っていて覚えている場合はDispose()、ファイナライザーで何もしません。それ以外の場合は、ファイナライザーで管理されていないリソースをクリーンアップします。そして、ここでは、これらの管理対象リソースについて気にする必要はありません。

4

2 に答える 2

1

if (disposing) {}ブロック内で正確に何をすべきですか?

管理対象リソースをクリーンアップします。つまりDispose()、その時点で所有しているすべてのIDisposableオブジェクトを呼び出します。

管理対象リソースを明示的にクリーンアップするには、オブジェクト内のすべてのフィールドなどをnullに設定するだけですか?

いいえ、それはそれを意味するものではありません。IDisposableオブジェクトについてのみです。

その言語でデストラクタ(またはファイナライザーと呼ばれるもの)を1つだけ持つ方が良いのではないでしょうか。

ファイナライザとも呼ばれるデストラクタは1つだけ ですが、Dispose()そうではありません。それはあなたの段落の残りを無関係にします。

DisposableパターンとGCがあり、それらは関連していて協力していますが、同じではありません。GCはメモリとメモリのみを管理します。IDisposableは、リソース(ストリーム、接続、ビットマップ)を管理するためのものです。

于 2013-01-28T14:14:23.797 に答える
1

基本的に、~Destructor()アンマネージフィールドまたはプロパティを持つクラスがある場合にのみ、disposeを使用して完全なパターンを実装する必要があります。

すべてのフィールドとプロパティが管理されており、使い捨てではない場合は、IDisposableを実装する必要はまったくありません。

フィールドまたはプロパティの1つが使い捨ての場合は、IDisposableパターンを実装するだけです。あなたは必ずしも上記のパターンで完全に独り占めする必要はありません。

最後のケースで、フィールドまたはプロパティにアンマネージリソースがある場合(たとえば、何かへのネイティブポインター、ADO以外のデータベース接続、または他のマネージ接続)、.netはガベージコレクターのときにそれをクリーンアップする方法を知りません。転がります。

この場合、オブジェクトがクリーンアップされる2つの場所を考慮する必要があります。開発者が必要に応じて呼び出してクリーンアップするDispose()か、忘れてしまいます。彼が忘れて、あなたがデストラクタを持っている場合、それはファイナライズキューに入れられます。

これがDispose(disposing)電話の出番です。開発者が優秀で電話をかけた場合はDispose()、管理対象リソースもクリーンアップできるようにtrueを送信します。

開発者がdisposeを呼び出しておらず、貧弱なオブジェクトがファイナライズキューに入れられた場合Dispose()、管理対象オブジェクトを呼び出すと、それらはもう存在しないため、例外がスローされます。したがって、この場合はFalseを送信して、管理対象リソースがスキップされ、例外が回避されるようにします。これについてはよくわかりませんが、ファイナライズキューに例外をスローするとプロセス全体が終了し、世界を終わらせる可能性さえあるという伝説があります。だからそれをしないでください。

于 2013-01-28T14:33:25.630 に答える