216 votes

Singleton par clarification Jon Skeet

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();
    }
}

Je souhaite mettre en œuvre Jon Skeet est un Singleton dans mon application en C#.

J'ai deux doutes sur le code

  1. Comment est-il possible d'accéder à l'extérieur de la classe imbriquée à l'intérieur de la classe? Je veux dire

    internal static readonly Singleton instance = new Singleton();
    

    Est quelque chose qui s'appelle la fermeture?

  2. Je n'ai pas eu ce commentaire

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

    qu'est-ce commentaire nous proposer?

363voto

Jon Skeet Points 692016
  1. Non, ce n'est rien à voir avec les fermetures. Une classe imbriquée a accès à l'extérieur de la classe députés, y compris le constructeur privé ici.

  2. Lire mon article sur beforefieldinit. Vous pouvez ou ne voulez pas le no-op constructeur statique, ça dépend de ce que la paresse des garanties dont vous avez besoin. Vous devez être conscient que .NET 4 changements de la réelle type d'initialisation de la sémantique un peu (toujours à l'intérieur de la spécification, mais plus qu'avant).

Avez-vous vraiment besoin de ce modèle? Êtes-vous sûr que vous ne pouvez pas aller loin avec:

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

     static Singleton() {}
     private Singleton() {}
 }

49voto

Stefan de Bruijn Points 4187

Au sujet de la question (1): La réponse de Jon est correct, puisqu'il a implicitement les marques de la catégorie "Imbriquées" privée en ne la rendant pas public ou interne :-). Vous pourriez aussi bien le faire explicitement par l'ajout de "privé":

    private class Nested

Au sujet de la question (2): essentiellement, ce que le post sur beforeinitfield et le type d'initialisation de vous dire que si vous n'avez pas de constructeur statique, le runtime peut l'initialiser à tout moment (mais avant de l'utiliser). Si vous avez un constructeur statique, votre code dans le constructeur statique peut initialiser les champs, ce qui signifie que le moteur d'exécution est seulement autorisé à initialiser le champ lorsque vous demandez pour le type.

Donc, si vous ne voulez pas le moteur d'exécution pour initialiser les champs de façon proactive avant de les utiliser, ajouter un constructeur statique.

De toute façon, si vous êtes à la mise en œuvre des singletons vous souhaitez initialiser comme des paresseux que possible, et non pas lorsque le moteur d'exécution pense qu'il doit initialiser vos variables -- ou vous avez probablement juste de ne pas les soins. À partir de votre question, je suppose que vous voulez le plus tard possible.

Qui apporte rencontré de Jon post sur singleton's, qui est de l'OMI, les sous-jacents au sujet de cette question. Oh, et les doutes :-)

Je tiens à rappeler que son singleton #3, il a marqué "mauvais", est en fait correcte (car lock automatiquement implique une barrière de mémoire sur la sortie). Il devrait également être plus rapide que le singleton #2 lorsque vous utilisez l'instance, plus d'une fois (ce qui est plus ou moins le point de singleton :-) ). Donc, si vous avez vraiment besoin d'un paresseux singleton mise en œuvre, je serais probablement aller pour un, pour la simple raisons que (1) il est très clair pour tout le monde qui lit votre code ce qui se passe et (2) vous savez ce qui va arriver avec des exceptions.

Dans le cas où vous vous poseriez la question: je n'aurais jamais utiliser singleton #6, car il peut facilement conduire à des blocages et un comportement inattendu avec des exceptions. Pour plus de détails, voir: paresseux du mode de verrouillage, plus précisément ExecutionAndPublication.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X