beforefieldinitフラグは何をしますか?


82

beforefieldinitフラグは何をしますか?クラスのILを調べると、このフラグが表示されますが、このフラグが実際に何をしているのかわかりません。

回答:


132

この問題に関する私の記事を参照してください

基本的にbeforefieldinitは、「静的フィールドが参照される前の任意の時点で型を初期化できる」ことを意味します。理論的には、これは非常に遅延して初期化できることを意味します。フィールドに触れない静的メソッドを呼び出す場合、JITは型を初期化する必要はありません。

実際には、クラスが他の場合より早く初期化されることを意味します。クラスを使用する可能性のある最初のメソッドの開始時に初期化しても問題ありません。これを、最初に実際に使用する直前に型の初期化を行う必要がある、beforefieldinit適用されていない型と比較してください。

したがって、次のようになります。

public static void DoSomething(bool which)
{
    if (which)
    {
        FirstType.Foo();
    }
    else
    {
        SecondType.Bar();
    }
}

両方の型がbeforefieldinit適用されている場合(C#では、型に静的コンストラクターがない限り、デフォルトで適用されます)、メソッドの開始時に両方が初期化されますDoSomething(通常は保証されません)。持っていない場合は、フラグに基づいて、そのうちの1つbeforefieldinitだけが初期化されます。

これが、シングルトンパターンを実装するときに静的コンストラクター(空のコンストラクターでも!)を使用するのが一般的である理由です。


「タイプは、フィールドが参照される前の任意の時点で初期化できます。」静的メソッドの実行にも当てはまりますか?
Royi Namir 2012

@ RoyiNamir、CLI仕様では、BeforeFieldInitが適用されると、「型の初期化メソッドは、その型に定義された静的フィールドへの最初のアクセス時またはその前に実行されます」と記載されています。その属性が欠落している場合(static .ctor)、「そのタイプの静的またはインスタンスフィールドへの最初のアクセス、またはそのタイプの静的、インスタンス、または仮想メソッドの最初の呼び出し」。したがって、静的メソッドが別の静的フィールドを参照しない限り、BeforeFieldInitが適用される場合は当てはまりません。
アルマン2013年

3
静的コンストラクター(つまり、beforefieldinitフラグを持たないクラス)を使用すると、パフォーマンスが低下することがわかりました。特定のクラスの静的メンバーを頻繁に呼び出す場合、ランタイムは、型がまだ初期化されているかどうかをテストするために、各呼び出しの前に追加のチェックを行う必要があるようです。beforefieldinitはこれらのチェックを回避します。ベンチマークのカップルが速くbeforefieldinitで50%程度だった:codeproject.com/Articles/87991/...
Qwertie

6

4.6で変更されるようです

https://github.com/dotnet/coreclr/issues/1193


素晴らしいので、これは、フィールドを初期化する最後の瞬間まで待機することを意味しますか(フィールドがあるかどうかに関係beforefieldinitなく)?
James Ko

1
最初に使用する前に、すべてのアクセスの前に初期化チェックが付けられます。その後、他のメソッドが変更されると、生成されたコードはフィールドに直接アクセスします。プリミティブ型の場合は、JIT時定数としても使用できます。
OmariO 2016

2
.Net4.0以降の型初期化の変更に関するJonの詳細な分析はこちら
RBT 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.