C#ではstaticなデストラクタを作ることができません。そこで、静的デストラクタっぽいことを実現するコードを考えたいと思います。
#そもそも静的デストラクタって必要?
クラスで使用するstatic変数がIDisposableなクラスの場合、
class TestClass
{
/// <summary>
/// 共通のバッファみたいな
/// </summary>
private static DisposableClass CommonBuffer = new DisposableClass();
/// <summary>
/// クラスが最初に呼ばれるときにメモリ確保したい
/// </summary>
static TestClass()
{
CommonBuffer.AllocMemory();
}
/// <summary>
/// 終了時にメモリを開放したい
/// </summary>
static ~TestClass() // ← staticなデストラクタはコンパイルエラーになる
{
CommonBuffer.Dispose();
}
}
の、ようにして終了時にDisposeしてやりたいのが人情というものです。どうせ終了するんだから構わないだろうという考え方もありですが、外部で作成されたライブラリを使う場合などは違ってくる場合があります。
初期化と終了処理の機能を備えたライブラリというのは結構あるものですが、そういったライブラリは
static void Main()
{
// 外部ライブラリの初期化
OuterLib.Initialize();
// メインの処理
// 外部ライブラリの終了処理
OuterLib.Finalize();
}
このような使い方を期待されているものだと思います。ですが、外部ライブラリを使用したクラスライブラリを開発する場合などは最初に示したような静的デストラクタで終了処理を行いたくなります。
また、カメラ等の外付けデバイスの操作用ライブラリ等の場合は、正しく終了処理を行ってやらないと次回正常に起動できないケースなども稀ながら存在します(特に他の部署が作った社内向けDLLとかの場合……)。そのため、やはり終了処理を行わないというわけにはいきません。
終了関数を新たに定義してアプリ終了時に呼ぶようにしてもらうというのも一つの手ですが、あまり親切ではありませんね。
#実装
以下のように内部Singletonクラスにデストラクタを定義してやれば、静的デストラクタのように扱うことができます。
class TestClass
{
/// <summary>
/// 静的デストラクタを実現するためのSingletonパターン
/// </summary>
private sealed class Destructor
{
/// <summary>
/// デストラクタ
/// </summary>
~Destructor()
{
// ここに終了処理を記述!!!
OuterLib.Finalize();
}
/// <summary>
/// Singletonパターンお決まりのprivateコンストラクタ、自クラスのインスタンス、インスタンス取得関数
/// </summary>
private Destructor() { }
private static Destructor instance = new Destructor();
public static Destructor GetInstance() { return instance; }
}
/// <summary>
/// 静的デストラクタ実現クラスのstaticな実体
/// </summary>
static private readonly Destructor destructor = Destructor.GetInstance();
}
プログラムの終了時にdestructorが破棄されてDestructorクラスのデストラクタが呼ばれるので、事実上TestClassの静的デストラクタのように扱うことができます。