2016-01-26 15 views
5

静的コンストラクタの必要性を理解しようとしています。私が見つけた情報のどれも、私が持っている質問に答えたものはありませんこの静的コンストラクタを理解しようとしています

class SimpleClass 
{ 
    // Static variable that must be initialized at run time. 
    static readonly long baseline = DateTime.Now.Ticks; 

    // Static constructor is called at most one time, before any 
    // instance constructor is invoked or member is accessed. 
    //static SimpleClass() 
    //{ 

    //} 
} 

とは対照的に、なぜあなたはこの

class SimpleClass 
{ 
    // Static variable that must be initialized at run time. 
    static readonly long baseline; 

    // Static constructor is called at most one time, before any 
    // instance constructor is invoked or member is accessed. 
    static SimpleClass() 
    { 
     baseline = DateTime.Now.Ticks; 
    } 
} 

をしますか?


これは他の質問とは異なりますが、これはパラメータを受け付けない静的コンストラクタに関するものです。

+0

これは静的な特定の質問ではなく、静的でない初期化に対しても有効です。 –

+0

[クラスのフィールドをコンストラクタで初期化するか、宣言で初期化できますか?](http://stackoverflow.com/questions/24551/initialize-class-field-in-constructor-or-at-declaration) –

+0

@CyrilGandonそうではありませんこれは、パラメータを受け付けない静的コンストラクタに関するものです。 dupeタグを削除することを検討してください。 –

答えて

5

何か明白です:静的メンバーのフィールド初期化以上のことをしたいとします。

あなたは、このクラスを持っている論理的場合:

class SimpleClass 
{ 
    // Static variable that must be initialized at run time. 
    static readonly long baseline = DateTime.Now.Ticks; 


} 

あなたは同じ効果持っていることを再書き込むことができます。

class SimpleClass 
{ 
    // Static variable that must be initialized at run time. 
    static readonly long baseline; 

    static SimpleClass() { 
     baseline = DateTime.Now.Ticks; 
    } 
} 

をしかし、その代わりに、あなたのようなあなたの静的コンストラクタにより行うことができますいくつかのプロパティを調べて(リフレクションを使用して)、いくつかのファーストアクセサ/ゲッタをエミュレートするか、またはあなたのタイプが作成された他のシステムに単純に通知するなどです。

From J C#の本を経由してeffreyリヒターCLR:

C#コンパイラがインライン 初期化(BeforeFieldInitクラス)を使用して、静的フィールドを持つクラスを見ているときに、コンパイラはBeforeFieldInitメタデータ フラグと クラスの型定義テーブルエントリを発します。 C#コンパイラが明示的なタイプの コンストラクタ(Preciseクラス)を持つクラスを参照すると、コンパイラはBeforeFieldInitメタデータフラグを持たないクラスのタイプ 定義テーブルエントリを生成します。 型のコンストラクタには、 の副作用を観察できる任意のコードを含めることができますが、フィールドにアクセスする前に静的フィールド の初期化を行う必要があります。このコードは正確な時間に実行する必要があります。

Obviouselly舞台裏で、この出来事以上の何かがある、私はC#の経由CLRから全体の章を読むことをお勧めしますが、「タイプコンストラクタ」

+5

静的コンストラクタを持つクラスは、静的フィールド初期化子のみを持つクラスと比べて、異なる初期化タイミングを持つことができます。 http://csharpindepth.com/Articles/General/Beforefieldinit.aspxを参照してください –

+0

私は静的なコンストラクタが必要な理由を示す例を表示できますか?私はそこで何ができますか?フィールドの初期化はできませんか? –

+0

@JonSkeetおそらく –

3

これは、可能な違いの例です。

class SimpleClass 
{ 
    static readonly long A = DateTime.Now.Ticks; 
    static readonly long B = DateTime.Now.Ticks; 

    static SimpleClass() 
    { 
    } 
} 

ABは、あなたは、コンストラクタでそれを書くとしたら、あなたはそれを保証することができますが、同じ値であることが保証されていません。

class SimpleClass 
{ 
    static readonly long A; 
    static readonly long B; 

    static SimpleClass() 
    { 
     var ticks = DateTime.Now.Ticks; 
     A = ticks; 
     B = ticks; 
    } 
} 

さらに、静的メンバーのインスタンス化のためにの注文事項があります。クラス宣言 の

静的フィールド変数初期化子は、それらが現れる テキストの順序で実行されている割り当ての配列に対応する:静的フィールドの初期化について、ECMA-334による

クラス宣言。 静的コンストラクター(§17.11)がクラスに存在する場合、 静的コンストラクターを実行する直前に、 静的フィールドイニシャライザーの実行が発生します。

class SimpleClass 
{ 
    public static readonly long A = IdentityHelper.GetNext(); 
    public static readonly long B = IdentityHelper.GetNext(); 

    static SimpleClass() 
    { 
    } 
} 

public static class IdentityHelper 
{ 
    public static int previousIdentity = 0; 
    public static int GetNext() 
    { 
     return ++previousIdentity; 
    } 
} 

:それ以外の場合は、静的フィールド初期化子の前

だからクラスの静的フィールドの最初の使用に実装依存時に実行 があり、我々はこのような何かを書くことができますここでABより前に割り当てられることが保証されています。この例では、A1B2となります。 A < B(アイデンティティがオーバーフローしておらず、スレッド化に問題がないと仮定して)保証することができます。今、私たちは次の場合に再オーダーフィールド:

public static readonly long B = IdentityHelper.GetNext(); 
public static readonly long A = IdentityHelper.GetNext(); 

機能が変化します。したがって、フィールド定義を並べ替えるだけですぐには解決できない副作用が発生しました。より多くの可能性の高いシナリオがある

、我々はこれをやってみたいことがあります。ここでは

class SimpleClass 
{ 
    public static readonly long A = IdentityHelper.GetExpensiveResult().A; 
    public static readonly long B = IdentityHelper.GetExpensiveResult().B; 

    static SimpleClass() 
    { 
    } 
} 

、我々はフィールド間GetExpensiveResult()を共有することができません。

+0

質問に関連していない小さなコードで、 'return ++ currentIdentity'が優れています。そうでないと、常にIdentityHelper.currentIdentity == IdentityHelper.GetNext()'が返されます。 –

+0

@DannyChenあなたは正解です - ) – Rob

+0

@ダニー・チェン、あなたはあなたの最後のコメントを詳述できますか?私はそれがどう働いているかをよく理解していません –

関連する問題