web-dev-qa-db-ja.com

スタティックファイナライザー

静的ファイナライズを実行する正しい方法は何ですか?

静的デストラクタはありません。 AppDomain.DomainUnloadイベントはデフォルトドメインでは発生しません。 AppDomain.ProcessExit eventは、すべてのイベントハンドラー間で3秒(デフォルト設定)の合計時間を共有するため、実際には使用できません。

43
Michael Damatov

基本的にはできません。可能な限りそれを回避する方法を設計します。

プログラムが常にとにかく突然終了する可能性があることを忘れないでください-誰かが力を引き出しているのは明らかな例です。したがって、あなたがすることはすべて「ベストエフォート」でなければなりません-その場合、私は確かに希望そのAppDomain.ProcessExitで十分でしょう。

あなたの特定のケースでは、あなたは何をする必要がありますか?

32
Jon Skeet

Herfried Wagnerは、これを実装する方法を説明する 優れた記事 をドイツ語(およびVB)で書いています。それでも、コードは理解できるはずです。

私はそれを試しました:

static readonly Finalizer finalizer = new Finalizer();

sealed class Finalizer {
  ~Finalizer() {
    Thread.Sleep(1000);
    Console.WriteLine("one");
    Thread.Sleep(1000);
    Console.WriteLine("two");
    Thread.Sleep(1000);
    Console.WriteLine("three");
    Thread.Sleep(1000);
    Console.WriteLine("four");
    Thread.Sleep(1000);
    Console.WriteLine("five");
  }
}

AppDomain.ProcessExitイベントとまったく同じように機能するようです。ファイナライザーは約を取得します。 3秒...

46
Michael Damatov

頭に浮かぶ2つの解決策:

  • 静的クラスは使用しないでください。非静的クラスを使用してインスタンス化する場合は、クリーンアップについてそれほど心配する必要はありません。
  • それが選択肢ではない場合、これはシングルトンを使用するのに適した状況であると私は主張します。これにより、オブジェクトのコピーがインスタンス化され、終了時にファイナライザーが呼び出されますが、それでもほとんどの場合、静的クラスのように扱うことができます。結局のところ、クラスはすでに静的であるため、シングルトンを使用しない一般的な理由のほとんどを共有しています。
8
Jason Baker

解放する必要のある静的メソッドに何をロードしているのか疑問に思います。私は確かにこれらのことを静的な方法で行うことをお勧めしません。

そうは言っても、静的メソッドは、finalizeメソッドを持つオブジェクトをインスタンス化する可能性があります。

6
Ady

Herfried K.Wagnerに基づくMichaelDamatovの回答(C#)を移植するため。 (VB.NET)これがC++/CLIバージョンです:

ref class MyClass
{
        ref class StaticFinalizer sealed
        {
            !StaticFinalizer();
        };
        static initonly StaticFinalizer^ stDestr = gcnew StaticFinalizer();
}

MyClass::StaticFinalizer::!StaticFinalizer()
{
    System::Diagnostics::Debug::WriteLine("In StaticFinalizer!");
}

P.S. AppDomain.ProcessExitメソッドと同様に、プロセスが異常終了した場合(たとえば、タスクマネージャーから)、このメソッドは呼び出されない場合があります。もう1つの注意点は、MyClassが汎用(テンプレート)の場合、その静的コンストラクターと静的デストラクタがアプリケーションの実行ごとに1回だけ呼び出されるという仮定は無効になるということです。

0
ILIA BROUDNO