11

ドキュメント (MSDN: link ) に基づいて、ファイナライザーを実装するときに IDisposable パターンを使用する必要があることは明らかです。

しかし、(オブジェクトを破棄する決定論的な方法を提供するために) IDisposable を実装し、クリーンアップするアンマネージ リソースがない場合、ファイナライザーを実装する必要がありますか?

私が見たように、クラスにマネージド リソースしかなく、Dispose を呼び出さない場合、マネージド リソースは GC によって自動的にクリーンアップされるため、ファイナライザーを実装する必要はありません。私が間違っている?

また、Dispose メソッドを使用してイベント ハンドラーをクリーンアップするとどうなるでしょうか。Dispose は GC によって自動的に呼び出されないため、イベント ハンドラーが配線されないようにするためにファイナライザーを実装する必要がありますか?

4

6 に答える 6

12

いいえ、IDisposable を実装するクラスがある場合 (つまり、パターンを正しく実装しており、破棄する管理リソースしかない場合) は、ファイナライザーを実装する必要はありません。

(そうすると、ファイナライザーを持つオブジェクトが GC のファイナライズ キューに追加され、必要以上に長く存続する可能性があるため、オブジェクトの有効期間に実際に影響を与える可能性があります。これは、オブジェクトが大きい場合に問題になる可能性があります。)

于 2010-10-07T14:46:43.933 に答える
11

管理されていないリソースがない限り、ファイナライザーを追加しないでください。

アンマネージ リソースではなくマネージド ディスポーザブル リソースを所有するクラスは、完全なDisposeパターンを実装する必要がありますが、ファイナライザーはありません。

クラスが でない場合、継承されたクラスがファイナライザーを追加する場合に備えて、そのメソッドでsealed呼び出す必要があります。GC.SuppressFinalize(this)Dispose()

于 2010-10-07T14:43:26.997 に答える
2
  1. いいえ、あなたのオブジェクトがアンマネージ リソースを保持するオブジェクトを保持している場合は、IDisposable を実装して、Dispose でその Dispose を呼び出すことができるようにする必要がありますが、ファイナライザーがその問題を処理するため、ファイナライザーは必要ありません。

  2. 実際、ファイナライザーのファイナライズ可能なメンバーで何かをしようとすると、ファイナライザーが実行される順序が決定論的ではないため、厄介なバグが発生する可能性があります。

  3. 原則として、クラスが 1 つまたは 0 つの管理されていないリソースを保持する方がはるかに優れています。また、管理されていないリソースが 1 つある場合は、それを処理するために必要な他の状態をできるだけ少なくする必要があります (つまり、他の破棄可能なメンバーはありません)。SafeHandle は、これに対処する良い方法です。クラスが複数のアンマネージド リソースを処理する必要がある場合は、これらのハンドラー クラスを介してリソースを処理する必要があります。次に、ファイナライザーと IDisposable が簡単になります。両方で処理する唯一のアンマネージド リソースがあるか (dispose が呼び出された場合はファイナライザーを抑制します)、IDisposable のみが必要です。

アンマネージ リソースを直接処理しなければならないことは比較的まれであるため、ファイナライザーを記述する必要はまったくない可能性があります (実際のコードで、一度はそうしたことがあると思います)。分別のある人は、管理されていないリソースを処理するクラスで他に多くのことをしないため、Dispose(bool) 全体も不要です。

于 2010-10-07T14:55:25.457 に答える
0

はい、管理されたリソースしかない場合、それらはガベージ コレクションが発生したときに GC によってクリーンアップされます (それらを指す生きた参照はありません)。

しかし、この場合、型に IDisposable を実装する必要があるのはなぜでしょうか? つまり、あなたの場合、オブジェクトを処分しないことは大きな問題ではないと考えているようですが、なぜ誰かがそれらを処分するのでしょうか?

また、ファイナライザーを使用している間は、ガベージ コレクションでパフォーマンスが低下することにも注意してください。ファイナライザーを使用するオブジェクトはすべて、最初の GC パスをエスケープするため、これらのオブジェクトの有効期間が短い場合、GC の効率が大幅に低下します。

オブジェクトをクリーンアップする必要がある最初のガベージ コレクションでは、ファイナライザーを実行するためにクリーンアップされません。オブジェクトは、すでにクリーニングされている必要がある場合でも、GC によって長命であると見なされます。

于 2010-10-07T14:46:29.360 に答える
0

マネージド リソースしかない場合は、IDisposable を実装する必要はまったくありません。IDisposable は、ネイティブ ハンドル、データベース接続など、GC のドメインを超えたものをクリーンアップすることを目的としています。

コントロールに IDisposable を実装するコントロールが含まれていて、ネイティブ リソースを解放する必要がある場合でも、IDisposable パターンを実装して、子コントロールに破棄する機会を与える必要があります。

ファイナライザで Dispose() を呼び出す理由は、最後の手段です。オブジェクトが適切に破棄されなかった場合、GC は最後の手段としてそれを行います。

于 2010-10-07T14:44:00.383 に答える
0

ファイナライザーを実装する必要はありませんでした。ご存知のように、GC の前に必要なことを何でも行う機会をオブジェクトに与えます。dispose メソッドですべてのリソースを解放する必要があります

于 2010-10-07T14:49:01.963 に答える