ファイナライザーが役立つことは非常にまれです。リンク先のドキュメントは完全に役立つわけではありません。次のかなり循環的なアドバイスを提供しています。
ファイナライズが必要なオブジェクトにのみ Finalize を実装する
これは質問をする良い例ですが、あまり役に立ちません。
実際には、ほとんどの場合、ファイナライザーは必要ありません。(.NET 開発者が経験しなければならない学習曲線の 1 つは、ファイナライザーが必要だと考えているほとんどの場所で、ファイナライザーが必要ないことを発見することです。) これを (とりわけ) WPF の質問としてタグ付けしました。ほとんどの場合、UI オブジェクトにファイナライザーを配置するのは間違いです。(したがって、ファイナライザーが必要であることが判明した異常な状況の 1 つにいる場合でも、その作業は、WPF に関係するコードの近くには属しません。)
ファイナライザーが役立つ可能性があると思われるほとんどのシナリオでは、実際にはそうではありません。ファイナライザーが実行されるまでには、有用なことを行うにはすでに遅すぎるためです。
たとえば、ファイナライザーが実行されるまでに、それらのオブジェクトはすでにファイナライズされている可能性があるため、オブジェクトが参照しているオブジェクトに対して何かをしようとするのは、通常は悪い考えです。(.NET は、ファイナライザーが実行される順序について保証しないため、参照先のオブジェクトがファイナライズされているかどうかを知る方法がありません。) ファイナライザーが既に実行されているオブジェクトでメソッドを呼び出すのは悪い考えです実行されました。
一部のオブジェクトが確実にファイナライズされていないことを知る方法がある場合は、それを使用しても安全ですが、それは非常に珍しい状況です (...問題のオブジェクトにファイナライザーがなく、ファイナライズ可能なリソース自体を使用しません.しかし、その場合、あなた自身のオブジェクトがなくなったときに実際に何かをする必要があるオブジェクトではないでしょう.)
ファイナライザーが役立つと思われる主な状況は相互運用です。たとえば、P/Invoke を使用してアンマネージ API を呼び出し、その API がハンドルを返すとします。おそらく、そのハンドルを閉じるために呼び出す必要がある他の API があるでしょう。それはすべて管理されていないものであるため、.NET GC はそれらのハンドルが何であるかを知りません。それらが確実にクリーンアップされるようにするのはあなたの仕事です。SafeHandle
そのシナリオに を使用します。
実際には、ファイナライザーを使用していることに気付いた唯一の場所は、a) GC の機能を調査するために設計された実験、および b) 特定のオブジェクトがシステムでどのように使用されているかについて何かを発見するために設計された診断コードです。どちらの種類のコードも最終的に本番環境に入るべきではありません。
したがって、「子クラスにもファイナライザーを実装する必要があるかどうか」に対する答えは、次のとおりです。尋ねる必要がある場合、答えはノーです。
フラグを複製するかどうかについては...他の回答がここで矛盾したアドバイスを提供しています。主なポイントは、1) ベースを呼び出す必要があること、Dispose
および 2)Dispose
べき等である必要があることです。(つまり、1 回、2 回、5 回、100 回呼び出されても問題ありません。2 回以上呼び出されても文句を言うべきではありません。)好きなように実装するのは自由です。ブール値のフラグは1つの方法ですがnull
、メソッドで特定のフィールドを に設定するだけで十分であることがよくあります。そのDispose
時点で、別のブール値フラグの必要性がなくなりDispose
ますnull
。
そこにあるガイダンスの多くはIDisposable
、ファイナライザーが必要な状況に対処しているため、非常に役に立ちませんが、実際には非常にまれなケースです。IDisposable
これは、多くの人が必要以上に複雑な実装を書いていることを意味します。実際には、ほとんどのクラスは、jpierson がリンクしている記事で、 Stephen Cleary が「レベル 1」と呼んでいるカテゴリを呼び出します。これらについては、ほとんどの例をごちゃごちゃにしているGC.KeepAlive
、GC.SuppressFinalize
、およびすべてのものは必要ありません。Dispose(bool)
これらの「レベル 1」タイプに対する Cleary のアドバイスが示すように、人生はほとんどの場合、実際にははるかに単純です。