.NET がデストラクタに最も近いものは、.NET がファイナライザと呼ぶものです。主な違いは、デストラクタは通常、決定論的なファイナライズ (たとえば、オブジェクトの参照カウントがゼロになったとき) を行うのに対し、.NET ファイナライザは、オブジェクトが参照されなくなった後の不確定な時間に呼び出されることです。これは、単純な参照カウントを使用するのではなく、ルート トレース手順を使用して .NET ガベージ コレクターによって処理されます。
これに関する最高の記事の 1 つは、ガベージ コレクション: Microsoft .NET Framework の自動メモリ管理です。特にファイナライザーの詳細については、MSDNの記事「 Finalize Methods and Destructors」を参照してください。
Destructor でクラスのプライベート メンバーにアクセスできませんか?
いいえ、安全に行うことはできません。
あなたの場合、オブジェクトがルートによって直接的または間接的に参照されなくなった場合、オブジェクトが参照する COM オブジェクト、つまり、プライベート フィールドによって参照されるオブジェクトもルートによって参照されないということです。また。(オブジェクトのフィールドによって参照されても、これらの COM オブジェクトは存続しません。これは、オブジェクトがルートによって参照されなくなったり、ルートからトレースされなくなったりするためです。したがって、COM オブジェクトはルートからもトレースされません。) したがって、オブジェクトとそれが参照するすべての COM オブジェクトは、すべて同時にガベージ コレクションの準備ができています。しばらくすると、ガベージ コレクターはオブジェクトをクリーンアップし、そのファイナライザーを呼び出します。これは、それぞれが実際にはランタイム呼び出し可能ラッパー (RCW)である COM オブジェクトに対しても行われます。.
問題は、これらのオブジェクトがガベージ コレクションされるタイミングが不確実であるだけでなく、ファイナライザーが呼び出される順序も非決定的であることです。この場合、Runtime Callable Wrapper には、 Marshal.ReleaseComObject自体を呼び出すファイナライザーもあり、この COM オブジェクトを解放できるように、フェンスの COM 側で参照カウントをデクリメントします。ただし、ファイナライザーが呼び出される順序は不明であるため、オブジェクトが参照する COM オブジェクトのファイナライザーが、オブジェクトのファイナライザーより前に起動する可能性が非常に高くなります。したがって、ファイナライザー内のコードは動作することもありますが、ほとんどの場合、オブジェクトが参照する 1 つ以上のランタイム呼び出し可能ラッパーは、ファイナライザーが既に呼び出されており、ファイナライザーがそのコードを実行する前に、基になる COM オブジェクトが解放されます。
つまり、一般的にファイナライザーの使用を避ける必要があり、ファイナライザー内から参照型にアクセスしないでください。これらの参照型は既にファイナライズされている可能性があるためです。
あなたの状況を改善するために、2 つの異なる可能性を検討します。
COM オブジェクトを作成した同じメソッド内で破棄します。これについては、こことここでいくつかの議論があります。
非決定論的なファイナライザーに頼るのではなく、 IDisposable インターフェイスを使用して、オブジェクトの決定論的な破棄を有効にします。
IDisposable パターンの実装方法に関する記事については、次を参照してください。
-- マイク