web-dev-qa-db-ja.com

シングルトンbyジョンスキートの説明

public sealed class Singleton
{
    Singleton() {}

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

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested() {}
        internal static readonly Singleton instance = new Singleton();
    }
}

C#での現在のアプリケーションで Jon Skeetのシングルトンパターン を実装したいと思います。

私はコードに2つの疑問があります

  1. ネストされたクラス内の外部クラスにアクセスするにはどうすればよいですか?というのは

    internal static readonly Singleton instance = new Singleton();
    

    閉鎖と呼ばれるものはありますか?

  2. このコメントを理解できません

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    

    このコメントは何を示唆していますか?

211
amutha
  1. いいえ、これはクロージャーとは関係ありません。ネストされたクラスは、ここのプライベートコンストラクターを含む、外部クラスのプライベートメンバーにアクセスできます。

  2. beforefieldinitの記事 を読んでください。 no-op静的コンストラクターが必要な場合とそうでない場合があります。これは、必要な遅延保証が何であるかによって異なります。 .NET 4 actual型の初期化セマンティクスを多少変更する (まだ仕様内ですが、以前より怠lazであることに注意してください) )。

あなたは本当にこのパターンが必要ですか?あなたは逃げることができないと確信しています:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();
    public static Singleton Instance { get { return instance; } }

    static Singleton() {}
    private Singleton() {}
}
354
Jon Skeet

質問(1)について:Jonの答えは正しいです。なぜなら、彼はクラスを「ネスト」クラスに公開または内部にしないことで暗黙的にマークしているからです:-)。 「プライベート」を追加して明示的に行うこともできます。

    private class Nested

質問(2)に関して:基本的に beforeinitfieldに関する投稿 および type initialization は、静的コンストラクターがない場合、ランタイムはいつでも初期化できることを伝えます(ただし、使用する前に)。静的コンストラクターがある場合、静的コンストラクター内のコードがフィールドを初期化する可能性があります。つまり、ランタイムは、タイプを要求したときにのみフィールドの初期化を許可されます。

したがって、ランタイムを使用する前にフィールドを「プロアクティブに」初期化したくない場合は、静的コンストラクターを追加します。

いずれにせよ、シングルトンを実装している場合は、ランタイムが変数を初期化する必要があると判断したときではなく、できるだけ遅延して初期化するか、おそらく気にしないでください。あなたの質問から私はあなたがそれらをできるだけ遅くしたいと思うと思います。

singleton 'sに関するJonの投稿に出会うと、IMOがこの質問の根底にあるトピックになります。ああ、疑い:-)

彼が「間違っている」とマークしたシングルトン#3が実際に正しいことを指摘したいと思います(ロックが自動的に 終了時にメモリバリアを意味する であるため)。また、インスタンスを複数回使用する場合は、シングルトン#2よりも高速である必要があります(これは、シングルトンのポイントとほぼ同じです:-))。だから、あなたが本当に怠singleなシングルトン実装が必要な場合、私はおそらくその1つに行きます-単純な理由のために(1)あなたのコードを読んでいる誰にとっても非常に明確であり、例外付き。

あなたが疑問に思っている場合:それは簡単にデッドロックと例外を伴う予期しない動作につながる可能性があるため、シングルトン#6を使用することはありません。詳細については、「 lazyのロックモード 」、特に「ExecutionAndPublication」を参照してください。

48
atlaste