C++/CLI でオブジェクトを適切にクリーンアップする方法を見つけようとしています。
私はこれらの 2つの記事 ( 1、2 )を読んだり、ざっと目を通したりして、標準を調べ、他のいくつかの質問、特にこの質問を調べました。
私はさまざまな情報を持っています:
- ファイナライザーはアンマネージ リソースをクリーンアップする必要があります (そのため、オブジェクトがガベージ コレクションされるとすべてがクリーンアップされます。
- デストラクタは、マネージド リソースをクリーンアップし (Foo または Foo.Dispose()? を削除)、ファイナライザを呼び出す必要があります ( 1に従って) 。
- デストラクタとファイナライザの両方を複数回呼び出すことができます ( 8.8.8 の3ページ 26 の終わりを参照)。
- デストラクタが呼び出された場合、ファイナライザはもう呼び出されません ( 1に従って) (CLR によってではありません。つまり、まだ自分で呼び出すことができます)。
- デストラクタは基本クラスのデストラクタを呼び出します ( 3ページ 25 を参照)。
- ファイナライザを持つクラスには、常にデストラクタが必要です (おそらく、アンマネージ リソースを確定的にクリーンアップするため)。
- ファイナライザーへの呼び出しは、基本クラスのファイナライザーを呼び出しません ( 3 19.13.2 p. 131)
しかし、一部には次の事実によって引き起こされる多くの混乱もあります。
- ファイナライザーは C# ではデストラクタと呼ばれます
- デストラクタは内部的に Dispose メソッドと Finalize メソッドを生成しますが (Finalize については不明)、Finalize メソッドはファイナライザではありません
- C++ ではデストラクタのセマンティクスが異なり、一般的に決定論的なクリーンアップとガベージ コレクションの両方を持つことの複雑さ
答えとして私が望むのは、クラスに含まれる可能性のあるさまざまな種類のデータ (マネージド、アンマネージド、マネージドだが使い捨てなど、他に考えられるものは何でも) と適切に記述されたデストラクタとファイナライザを含むクラスの例です。
さらに具体的な質問が 2 つあります。
bool hasBeenCleanedUp
メンバーを持ち、デストラクタ/ファイナライザのコード全体を条件付きにするだけで、複数回呼び出される可能性に対処することは受け入れられますか?- GC によってクリーンアップされている可能性があるため、デストラクタによってのみクリーンアップでき、ファイナライザではクリーンアップしてはならないデータはどれですか?