Finalize メソッドおよびデストラクタ
アプリケーションで作成されるオブジェクトの大部分については、.NET Framework のガベージ コレクタによって、必要なすべてのメモリ管理タスクを暗黙的に実行できます。しかし、アンマネージ リソースをカプセル化したオブジェクトを作成する場合は、アプリケーションでそのオブジェクトの使用が終了した時点で、アンマネージ リソースを明示的に解放する必要があります。アンマネージ リソースの最も一般的な種類は、ファイル、ウィンドウ、ネットワーク接続などのオペレーティング システム リソースをラップしたオブジェクトです。ガベージ コレクタは、アンマネージ リソースをカプセル化したオブジェクトを有効期間全体にわたって監視できますが、そのリソースをクリーンアップする方法については具体的な情報を持っていません。このような種類のオブジェクトのために、.NET Framework には Object.Finalize メソッドが用意されています。このメソッドを使用すると、オブジェクトで使用するメモリをガベージ コレクタが再利用するときに、使用するオブジェクトが自身のアンマネージ リソースを正しくクリーンアップできるようになります。既定では、Finalize メソッドは何も実行しません。ガベージ コレクタが、オブジェクトのメモリを再利用する前にオブジェクトをクリーンアップするようにするには、クラス内で Finalize メソッドをオーバーライドする必要があります。
メモ : |
---|
C# で Finalize メソッドを実装するには、デストラクタ構文を使用する必要があります。.NET Framework Version 2.0 の Visual C++ には Finalize メソッドを実装するための独自の構文が用意されています。詳細については、「Destructors and Finalizers in Visual C++」を参照してください。.NET Framework Version 1.0 および 1.1 では Visual C++ でも、C# と同じように、Finalize メソッドに対してデストラクタ構文が使用されていました。 |
ガベージ コレクタは、終了キューと呼ばれる内部構造を使って、Finalize メソッドを持つオブジェクトを監視します。アプリケーションで Finalize メソッドを持つオブジェクトが作成されるたびに、ガベージ コレクタは、そのオブジェクトを指すエントリを終了キューに置きます。終了キューには、ガベージ コレクタによって再利用される前にその終了コードが呼び出される必要のある、マネージ ヒープ内のすべてのオブジェクトのエントリが格納されています。
メモ : |
---|
System.GC.KeepAlive(System.Object) メソッドのコード例では、再利用するオブジェクトのメンバがまだ実行中の場合でも、ガベージ コレクションがファイナライザを実行しようとします。これを避けるために KeepAlive メソッドを使用する方法を紹介します。 |
Finalize メソッドからは例外をスローしません。アプリケーションは例外を処理できないので、それが原因で異常終了する可能性があります。
Finalize メソッドまたはデストラクタを実装するとパフォーマンスが低下する場合があります。したがって、このメソッドまたはデストラクタは必要なときだけ使用してください。Finalize メソッドを持つオブジェクトが使用していたメモリを再利用するには、少なくとも 2 回のガベージ コレクションが必要です。ガベージ コレクタは、コレクションの実行時に、終了処理を持たないアクセスできないオブジェクトのメモリを再利用します。この時点では、終了処理を持つアクセスできないオブジェクトにはコレクションを実行できません。代わりに、これらのオブジェクトのエントリを終了キューから削除し、終了準備完了のマークを付けられたオブジェクトのリストに登録します。このリストのエントリは、終了コードを呼び出す準備ができているマネージ ヒープ内のオブジェクトを指します。ガベージ コレクタはこのリスト内のオブジェクトの Finalize メソッドを呼び出し、オブジェクトのエントリをリストから削除します。2 回目のガベージ コレクションは、終了したオブジェクトを指すエントリが、終了準備完了のマークを付けられたオブジェクトのリストに含まれていないので、これらのオブジェクトが本当に不要であると判断します。この 2 回目のガベージ コレクションで、オブジェクトのメモリが実際に再利用されます。