web-dev-qa-db-fra.com

Qu'est-ce qu'un singleton en C #?

Question assez simple.

Qu'est-ce qu'un singleton et quand devrais-je l'utiliser?

166
Sergio Tapia

Un singleton est une classe qui ne permet de créer qu'une seule instance d'elle-même et donne un accès simple et facile à cette instance. Le principe de singleton est une tendance dans le développement de logiciels.

Il existe une implémentation C # "Implémentation du motif Singleton en C #" couvrant la majeure partie de ce que vous devez savoir - y compris quelques bons conseils concernant la sécurité du thread .

Pour être honnête, il est très rare que vous ayez besoin de mettre en oeuvre un singleton - à mon avis, cela devrait être une de ces choses dont vous devriez être au courant, même s'il n'est pas utilisé trop souvent.

132
Daniel May

Vous avez demandé C #. Exemple trivial:


public class Singleton
{
    private Singleton()
    {
        // Prevent outside instantiation
    }

    private static readonly Singleton _singleton = new Singleton();

    public static Singleton GetSingleton()
    {
        return _singleton;
    }
}
51
Chris Simmons

Qu'est-ce que c'est: Une classe pour laquelle il n'y a qu'une seule instance persistante sur la durée de vie d'une application. Voir Singleton Pattern .

Quand l'utiliser: Le moins possible. Seulement lorsque vous êtes absolument certain que vous en avez besoin. Je suis réticent à dire "jamais", mais il existe généralement une meilleure alternative, telle que l'injection de dépendance ou simplement une classe statique.

39
Aaronaught

une autre façon d'implémenter singleton en c #, je préfère personnellement cette façon, car vous pouvez accéder à l'instance de la classe singeton en tant que propriété plutôt qu'en tant que méthode.

public class Singleton
    {
        private static Singleton instance;

        private Singleton() { }

        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                    instance = new Singleton();
                return instance;
            }
        }

        //instance methods
    }

mais bon, autant que je sache, les deux voies sont considérées comme "correctes", donc c'est simplement une question de goût personnel.

24
Marnix v. R.
using System;
using System.Collections.Generic;
class MainApp
{
    static void Main()
    {
        LoadBalancer oldbalancer = null;
        for (int i = 0; i < 15; i++)
        {
            LoadBalancer balancerNew = LoadBalancer.GetLoadBalancer();

            if (oldbalancer == balancerNew && oldbalancer != null)
            {
                Console.WriteLine("{0} SameInstance {1}", oldbalancer.Server, balancerNew.Server);
            }
            oldbalancer = balancerNew;
        }
        Console.ReadKey();
    }
}

class LoadBalancer
{
    private static LoadBalancer _instance;
    private List<string> _servers = new List<string>();
    private Random _random = new Random();

    private static object syncLock = new object();

    private LoadBalancer()
    {
        _servers.Add("ServerI");
        _servers.Add("ServerII");
        _servers.Add("ServerIII");
        _servers.Add("ServerIV");
        _servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
        if (_instance == null)
        {
            lock (syncLock)
            {
                if (_instance == null)
                {
                    _instance = new LoadBalancer();
                }
            }
        }

        return _instance;
    }

    public string Server
    {
        get
        {
            int r = _random.Next(_servers.Count);
            return _servers[r].ToString();
        }
    }
}

J'ai pris le code de dofactory.com , rien d'aussi luxueux que Je trouve cela bien supérieur aux exemples avec Foo et Bar en plus livre de Judith Bishop sur C # 3.0 Design Patterns donne un exemple d'application active dans mac dock.

Si vous examinez le code, nous construisons de nouveaux objets sur pour une boucle , ce qui crée un nouvel objet mais réutilise une instance à la suite de laquelle oldbalancer et newbalancer a même instance, comment? c'est dû à static mot clé utilisé sur la fonction GetLoadBalancer () , malgré ayant une valeur de serveur différente qui est une liste aléatoire, static on GetLoadBalancer () appartient au type lui-même et non à un objet spécifique.

De plus, il y a double vérification ici

if (_instance == null)
            {
                lock (syncLock)
                {
                    if (_instance == null)

depuis de MSDN

Le mot clé lock garantit qu’un thread n’entre pas dans une section de code critique, tandis qu’un autre thread se trouve dans la section critique. Si un autre thread tente d'entrer un code verrouillé, il attendra, bloquera, jusqu'à ce que l'objet soit libéré.

ainsi, chaque verrou d'exclusion mutuelle est émis, même s'il n'est pas nécessaire, ce qui est inutile; nous avons donc un contrôle nul.

Espérons que cela aide à nettoyer plus.

Et s'il vous plait, commentez si je comprends bien.

10
brykneval

Un singleton (et cela n'est pas lié à C #, c'est un modèle de conception OO) vous permet d'autoriser la création d'UNE SEULE instance d'une classe dans votre application. Les utilisations incluent généralement des ressources globales, bien que, d’expérience personnelle, c’est très souvent une source de grande douleur.

6
BFree

Bien qu'il ne puisse y avoir qu'une seule instance d'un singleton, ce n'est pas la même chose qu'une classe statique. Une classe statique ne peut contenir que des méthodes statiques et ne peut jamais être instanciée, alors que l'instance d'un singleton peut être utilisée de la même manière que tout autre objet.

5
TabbyCool

Je l'utilise pour les données de recherche. Charger une fois à partir de DB.

public sealed class APILookup
    {
        private static readonly APILookup _instance = new APILookup();
        private Dictionary<string, int> _lookup;

        private APILookup()
        {
            try
            {
                _lookup = Utility.GetLookup();
            }
            catch { }
        }

        static APILookup()
        {            
        }

        public static APILookup Instance
        {
            get
            {
                return _instance;
            }
        }
        public Dictionary<string, int> GetLookup()
        {
            return _lookup;
        }

    }
2
Manish Jain

C'est un modèle de conception et ce n'est pas spécifique à c #. Pour en savoir plus sur Internet et SO, comme sur ce article de wikipedia .

En génie logiciel, le motif singleton est un motif de conception utilisé pour limiter l'instanciation d'une classe à un seul objet. Ceci est utile lorsqu'un seul objet est nécessaire pour coordonner les actions à travers le système. Le concept est parfois généralisé aux systèmes qui fonctionnent plus efficacement quand il n’ya qu’un seul objet ou qui limitent l’instanciation à un certain nombre d’objets (par exemple cinq). Certains le considèrent comme un anti-modèle, jugeant qu'il est surexploité, introduit des limitations inutiles dans les situations où une seule instance d'une classe n'est pas réellement requise et introduit un état global dans une application.

Vous devriez l'utiliser si vous voulez une classe qui ne peut être instanciée qu'une seule fois.

2
marcgg

Qu'est-ce qu'un singleton:
C’est une classe qui ne permet de créer qu’une seule instance et donne généralement un accès simple à cette instance.

Quand devriez-vous utiliser:
Ça dépend de la situation.

Remarque: veuillez ne pas utiliser sur une connexion à une base de données. Pour une réponse détaillée, veuillez reportez-vous à à la réponse de @Chad Grant

Voici un exemple simple de Singleton:

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

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

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

Vous pouvez également utiliser Lazy<T> pour créer votre Singleton.

Voir ici pour un exemple plus détaillé utilisant Lazy<T>

2
MSTdev

Voici ce qu'est singleton: http://en.wikipedia.org/wiki/Singleton_pattern

Je ne connais pas C #, mais c'est en fait la même chose dans toutes les langues, seule l'implémentation diffère.

Vous devriez généralement éviter le singleton quand c'est possible, mais dans certaines situations, c'est très pratique.

Désolé pour mon anglais ;)

1
radex

La classe Singleton est utilisée pour créer une instance unique pour l'ensemble du domaine d'application.

public class Singleton
{
    private static Singleton singletonInstance = CreateSingleton();

    private Singleton()
    {
    }

    private static Singleton CreateSingleton()
    {
        if (singletonInstance == null)
        {
            singletonInstance = new Singleton();
        }

        return singletonInstance;
    }

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

Dans cet article est décrit comment nous pouvons créer une classe singleton thread-safe en utilisant une variable readonly et son utilisation pratique dans les applications.

1
Vikram

Nous devons utiliser le modèle de conception Singleton en C # lorsque nous devons nous assurer qu'une seule instance d'une classe particulière va être créée, puis fournir un accès global simple à cette instance pour l'ensemble de l'application.

Scénarios en temps réel dans lesquels vous pouvez utiliser le modèle de conception Singleton: Proxy de service: Comme nous le savons, l’appel d’une API de service est une opération de grande envergure dans une application. Le processus qui prend le plus de temps est la création du client de service afin d'appeler l'API de service. Si vous créez le proxy de service en tant que Singleton, cela améliorera les performances de votre application.

Façades: Vous pouvez également créer les connexions à la base de données en tant que Singleton, ce qui peut améliorer les performances de l'application.

Journaux: dans une application, effectuer l'opération d'E/S sur un fichier est une opération coûteuse. Si vous créez votre enregistreur en tant que Singleton, cela améliorera les performances de l'opération d'E/S.

Partage de données: si vous avez des valeurs constantes ou des valeurs de configuration, vous pouvez les conserver dans Singleton afin qu'elles puissent être lues par d'autres composants de l'application.

Mise en cache: Comme nous le savons, récupérer les données d'une base de données est un processus qui prend du temps. Dans votre application, vous pouvez mettre en mémoire cache le maître et la configuration, ce qui évitera les appels à la base de données. Dans de telles situations, la classe Singleton peut être utilisée pour gérer la mise en cache avec la synchronisation de threads de manière efficace, ce qui améliore considérablement les performances de l'application.

Inconvénients du motif de conception Singleton en C # Les inconvénients de l'utilisation du motif de conception Singleton en C # sont les suivants:

Le test unitaire est très difficile car il introduit un état global dans une application. Cela réduit le potentiel de parallélisme au sein d'un programme, car pour accéder à l'instance singleton dans un environnement multi-thread, vous devez sérialiser l'objet à l'aide du verrouillage.

J'ai pris ceci de l'article suivant.

https://dotnettutorials.net/lesson/singleton-design-pattern/

0
Pranaya Rout

Je sais qu'il est très tard pour répondre à la question, mais avec Auto-Property, vous pouvez faire quelque chose comme ça:

public static Singleton Instance { get; } = new Singleton();

Singleton est votre classe et peut être via, dans ce cas, la propriété en lecture seule Instance.

0
Zyo

E.X Vous pouvez utiliser Singleton pour les informations globales devant être injectées.

Dans mon cas, je conservais les détails de l'utilisateur enregistré (nom d'utilisateur, autorisations, etc.) dans la classe statique globale. Et lorsque j'ai essayé d'implémenter le test unitaire, il était impossible d'injecter une dépendance dans les classes de contrôleur. Ainsi, j'ai changé mon motif Static Class en Singleton.

public class SysManager
{
    private static readonly SysManager_instance = new SysManager();

    static SysManager() {}

    private SysManager(){}

    public static SysManager Instance
    {
        get {return _instance;}
    }
}

http://csharpindepth.com/Articles/General/Singleton.aspx#cctor

0
n3xus