デストラクター (C# プログラミング ガイド)
デストラクターは、クラスのインスタンスを消滅させるために使用します。
解説
デストラクターは、構造体には定義できません。クラスでだけ使用します。
クラスで使用できるデストラクターは 1 つだけです。
デストラクターを継承またはオーバーロードすることはできません。
デストラクターを呼び出すことはできません。デストラクターは自動的に起動されます。
デストラクターは修飾子をとらず、パラメーターはありません。
次に示すのは、Car クラスに対するデストラクターの宣言の例です。
class Car
{
~Car() // destructor
{
// cleanup statements...
}
}
デストラクターは、オブジェクトの基本クラスで Finalize を暗黙的に呼び出します。したがって、前のデストラクターのコードは、暗黙的に次のコードに解釈されます。
protected override void Finalize()
{
try
{
// Cleanup statements...
}
finally
{
base.Finalize();
}
}
つまり、最派生クラスから最低派生クラスまで、継承チェーンのすべてのインスタンスに対して、Finalize メソッドが再帰的に呼び出されます。
[!メモ]
空のデストラクターは使用しないでください。デストラクターがクラスに存在するときは、エントリが Finalize キューで作成されます。デストラクターを呼び出すと、ガベージ コレクターが呼び出され、このキューを処理します。デストラクターが空の場合は、パフォーマンスを不必要に低下させるだけです。
デストラクターがいつ呼び出されるかはガベージ コレクターによって決定されるため、プログラマは制御できません。ガベージ コレクターは、アプリケーションが使用していないオブジェクトをチェックします。消滅できるオブジェクトと考えられる場合、デストラクター (存在する場合) を呼び出し、オブジェクトの格納に使用されているメモリをクリアします。デストラクターは、プログラムの終了時にも呼び出されます。
Collect を呼び出すことによって、ガベージ コレクションを強制的に行うことができます。ただし、パフォーマンスに問題が発生する可能性があるため、通常はこの処理を避けます。
デストラクターを使ったリソースの解放
一般に C# では、ガベージ コレクションを使用しない言語で開発する場合ほど、メモリ管理を必要としません。.NET Framework のガベージ コレクターが、オブジェクトに対するメモリの割り当てと解放を暗黙的に管理します。ただし、ウィンドウ、ファイル、ネットワーク接続などのアンマネージ リソースをアプリケーションでカプセル化するときは、デストラクターを使ってこれらのリソースを解放する必要があります。オブジェクトを消滅させることができる場合、ガベージ コレクターはそのオブジェクトの Finalize メソッドを実行します。
リソースの明示的な解放
アプリケーションで貴重な外部リソースを使用している場合は、ガベージ コレクターがオブジェクトを解放する前にリソースを明示的に解放する手段を用意することをお勧めします。この処理を行うには、オブジェクトに対して必要なクリーンアップを実行する Dispose メソッドを IDisposable インターフェイスから実装します。これによって、アプリケーションのパフォーマンスを大幅に向上させることができます。このようにリソースを明示的に制御する場合でも、デストラクターは、Dispose メソッドの呼び出しが失敗したときにリソースをクリーンアップするための安全装置になります。
リソースのクリーンアップの詳細については、次のトピックを参照してください。
使用例
次の例では、継承のチェインを形成する 3 つのクラスを作成します。First が基本クラスであり、Second は First から派生し、Third は Second から派生しています。3 つのクラスのいずれにもデストラクターがあります。Main() では、最派生クラスのインスタンスが作成されます。プログラムを実行すると、3 つのクラスのデストラクターが、最派生クラスから最低派生クラスの順に自動的に呼び出されます。
class First
{
~First()
{
System.Diagnostics.Trace.WriteLine("First's destructor is called.");
}
}
class Second : First
{
~Second()
{
System.Diagnostics.Trace.WriteLine("Second's destructor is called.");
}
}
class Third : Second
{
~Third()
{
System.Diagnostics.Trace.WriteLine("Third's destructor is called.");
}
}
class TestDestructors
{
static void Main()
{
Third t = new Third();
}
}
/* Output (to VS Output Window):
Third's destructor is called.
Second's destructor is called.
First's destructor is called.
*/
C# 言語仕様
詳細については、「C# 言語仕様」を参照してください。言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。