web-dev-qa-db-ja.com

C#オブジェクトを手動で破棄する

私はC#を学ぶのはかなり新しいです(Java C++背景)から、手動のゴミ処理について質問があります:C#でオブジェクトを手動で破壊することさえ可能ですか?IDisposableインターフェイス、しかし、私が書いていないクラスを扱っていて、それを実装していないと仮定しますか?.Dispose()メソッドがないので、それとusing { }は外にあり、.Finalizeは常にprotectedまたはprivateのいずれかなので、オプションでもありません。

(この場合、C#でpossibleとは何かを学ぼうとしています。他のすべてが失敗した場合はinherit仮定のImNotDisposableクラス。そのため、doesはIDisposableを実装します。

30
East of Nowhere

.Netオブジェクトを手動で破棄することはありません。それが、管理された環境であることのすべてです。

実際、オブジェクトが実際に到達可能である場合、つまり、GCに破棄するオブジェクトを伝えるために使用できる参照がある場合、そのオブジェクトの収集は不可能になります。 GCはneverまだ到達可能なオブジェクトを収集します。

できることは、GC.Collect()を呼び出して、一般的なコレクションを強制することです。しかし、これはほとんど良い考えではありません。

代わりに、アンマネージリソースを使用せず、プログラム内の他のオブジェクトが到達できないオブジェクトを単純にpretendすることをお勧めします。私はこれが起こらないことを知っていますが、この時点ではオブジェクトは他のメモリと同じように単なるメモリのブロックです。あなたはそれを回収することはできず、最終的に収集されるので、あなたにも死んでしまうかもしれません。

IDisposableに関する最後のメモ。 unmanagedリソースをラップするタイプ(ソケット、データベース接続、gdiオブジェクトなど、および時折のイベント/デリゲートサブスクリプション)にのみ使用する必要があります。

30
Joel Coehoorn

オブジェクトに到達できない場合、GC.Collect()を呼び出すことができ、オブジェクトは破棄されます。 IDisposableの概念はCLRとは関係がなく、主に追加廃棄ロジックを実行するために実装するユーザーコード用です。オブジェクトでDispose()を呼び出しても、オブジェクト自体がメモリから解放されるわけではありませんが、このオブジェクトが参照するリソースを破棄する可能性があります。

私が言ったことはこれを達成する方法ですが、99.9999%のアプリケーションではGC.Collect()を呼び出さないでくださいdegrade代わりにアプリケーションのパフォーマンスそれを改善する。

7
Eilon

ガベージコレクションをトリガーすることはできますが(ファイナライズ可能なオブジェクトがどの世代にあるのかわからないため、すべての世代でGCをトリガーする必要があります)、特定のオブジェクトのファイナライズを必ずしも強制することはできません。ガベージコレクターがどのように機能するかについての仮定にのみ依存できます。

さらに、ファイナライズは独自のスレッドで行われるため、ガベージコレクションのトリガー後に WaitForPendingFinalizers を呼び出す必要があります。

GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();

他の人が指摘したように、これは実際にアプリケーションのパフォーマンスを損なう可能性があります。GCを不必要に呼び出すと、短命のオブジェクトをより高い世代に昇格させる可能性があるためです。

一般的に、ファイナライザ(デストラクタ)を実装し、IDisposableを実装しないクラスは眉をひそめます。そして、IDisposableを実装するものはすべて、そのファイナライザロジックを呼び出して、ガベージコレクションでのファイナライズを抑制する必要があります。

Jeff Richterさんが ガベージコレクションの発生時に通知を受け取る のための素敵なちょっとしたトリックを最近投稿しました。

ガベージコレクターの基本とパフォーマンスのヒント = Rico Mariani(MSFT)に関する別のすばらしい記事

7
Josh

いいえ、特定のオブジェクトを破棄することはできません。

ガベージコレクターを呼び出すことができます。ガベージコレクターは、破壊するオブジェクトを探しますが、ほとんど決して良い考えではありません。

6
Jay Bazuzi

あなたはcanあなたが破壊したい変数がスコープ外になった後にガベージコレクタを強制的に実行しますが、通常はそうしたくありませんガベージコレクターは、独自の作業を行うために残されている場合、より効率的です。

強制的なガベージコレクションは GC.Collect で実行できますが、実行しないでください。 .NET開発者としての10年間で、私はそれを必要としませんでした。

4
Mark Seemann

オブジェクトを決定論的に破壊することはできません。 CLRは、フラグが立てられたオブジェクトがいつ回収されるかを決定します。これは、オブジェクトにフラグを立ててフラグを立て、マネージドリソースとアンマネージドリソースを確実に破棄できるようにしますが(IDisposableパターンを実装することにより)、メモリが解放される実際の時間はCLRまでです。これは、実際に何かを削除し、その後リリースされるC++とは異なります。

2
Scott Davies

できない「C++削除」のようにオブジェクトを手動で破棄します。できることは、オブジェクトが取得した排他的リソースをすべて閉じ、GCが収集できるようにこのオブジェクトへのすべての参照をnullにするだけです。また、GC.Collect()を自分で呼び出さないでください。メモリからオブジェクトを安全に収集するために他のすべてのスレッドを中断する必要があるため、GCプロセスは高価です。GCを信頼するだけで、必要に応じて開始されます。

2
bashmohandes

クラスマトリックスがあり、2つのマトリックスオブジェクトaMatrixbMatrixを作成したとします。 C#では、次のようにオブジェクトを手動で破棄(最終化)できます。

aMatrix = null;

GC.Collect();

ガベージコレクターは、aMatrixがnullであることを認識し、それを破棄(最終化)します。これが良いアイデアであるかどうかは、別の話です。

1
MrGuest123