2016-05-24 12 views
4

Jon Skeetは、singletonの最大の怠惰が必要な場合は、コンパイラにbeforefieldinitとしてマークするような静的コンストラクタを追加する必要があることを示唆しています。スタティックコンストラクタを使用したシングルトン実装の怠惰

しかし、私はいくつかのテストを行いました。それはなしで、 beforefieldinitです。

コードサンプルは、(プライベートコンストラクタ呼び出しの出力がコンソールへとフィールドが初期化されたことを確認します

public sealed class Singleton 
{ 
    private static readonly Singleton instance = new Singleton(); 

    public static string Stub() 
    { 
     return "123"; 
    } 

    // Explicit static constructor to tell C# compiler 
    // not to mark type as beforefieldinit 
    //static Singleton() 
    //{ 
    //} 
    private Singleton() 
    { 
     Console.WriteLine("private ctor"); 
    } 

    public static Singleton Instance 
    { 
     get 
     { 
      return instance; 
     } 
    } 
} 

私はSingleton.Stub(呼び出し)プライベートコンストラクタがヒットされて、私はコメントを解除されていません静的コンストラクタは、プライベートコンストラクタは常に呼び出されます。

これは私が静的コンストラクタによって作られたトラックができる唯一の違いです。beforefieldinitは私がきた何をするかの違いを理解する私の試みにおいて

また、Skeetの答えin this postを読んでDoSomething()にfalseを渡してみました。静的コンストラクタの有無にかかわらず、プライベートコンストラクタは呼び出されていません。

public static void DoSomething(bool which) 
{ 
    if (which) 
    { 
     var a = Singleton.Stub(); 
    } 
    else 
    { 
     Faketon.Stub(); 
    } 
} 
+0

ここで 'which'の値は何ですか?おそらく 'false'のように聞こえます。 –

+0

最初のコードサンプルはDoSomething()メソッドを使用していません。私は、単にfalseである2番目のコードサンプルのMain()..から 'Singleton.Stub()'を呼び出します。 – BornToCode

+0

これはおそらく 'DoSomething(false)'メソッドに定数を渡し、 'if'ステートメントが最適化され、' Singleton.Stub() 'がコードから最適化/削除されたためです。 –

答えて

5

私はSingleton.Stub(コール)私は、静的ctorのプライベートconstuctorが常に呼び出されたコメントを解除したときにプライベートコンストラクタは、ヒットされていません。

whichの値がここで何をクリアしていないが、基本的に次の4つのケースを持っている:

  • 静的コンストラクタは、Singleton.Stubと呼ばれる:タイプ初期化子が
  • 静的コンストラクタを実行することが保証されて、 Singleton.Stubが呼び出されていない:型初期化子が実行されないことが保証されている
  • スタティックコンストラクタなし、Singleton.Stubと呼ばれる:型初期化子実行あなたが使用するSingleton.Stubを変更した場合のみ、という点で異なるかもしれ実行タイプ初期化子が、

最後の2例に保証するものではありません:

  • ない静的コンストラクタに保証されていない、Singleton.Stubは呼び出されません3番目のケースは "型初期化子の実行が保証される"となります。

  • +0

    1.なぜ上記の記事で、完全な怠惰のために静的なctorを追加することを提案しますか?スタブがスタティックctorなしで呼び出されると、初期化子が実行され、スタティックctorで常に実行されます。 2。'Singleton.Stubが呼び出されない:型初期化子が実行される可能性がありますが、保証されません ' - 型初期化子が青色から使い果たす可能性があります。 – BornToCode

    +0

    @BornToCode:1)私の完全に怠惰なバージョンは、 'Instance'が使用されている場合にのみ初期化される入れ子型で静的コンストラクタを使用します。コードにネストされた型はありません。同じシナリオではありません。 2)メソッドが最初に実行されるとき、JITコンパイラがメソッドによって必要とされる可能性のあるすべての型を初期化することは合理的です(ただし必須ではありません)。つまり、タイプ*が初期化されたかどうかを毎回確認する必要はありません。 –

    関連する問題