C # में एक सिंगलटन क्या है?


181

एक सिंगलटन क्या है और मुझे इसका उपयोग कब करना चाहिए?


2
संभव डुप्लिकेट: stackoverflow.com/questions/246710/…
मार्क सीमन

4
इसके अलावा, सिंगलटन OO प्रोग्रामिंग में सबसे व्यापक रूप से उपयोग और दुरुपयोग की जाने वाली डिज़ाइन पैटर्न में से एक है।
चोसपांडियन

3
@ फैबियानो: क्योंकि इसमें कपल्स बनाने का एक तरीका है जिससे कोई मतलब नहीं है (मैं कैसे Xबात कर सकता हूं Y? बस Yएक सिंगलटन बनाइए?), जो बदले में परीक्षण / डिबगिंग और प्रोग्रामिंग की एक प्रक्रियात्मक शैली की ओर जाता है। कभी-कभी सिंगलटन आवश्यक होते हैं; अधिकांश समय, नहीं।
आरोनॉट

3
यह मेरे मानक फोन साक्षात्कार प्रश्नों में से एक है। सही उत्तर है: कभी नहीं।
जॉनी

3
@ जोनी अच्छी है, यह संभावित डेवलपर्स को चेतावनी देने में मदद करती है कि बॉस कैसा है!
मिस्टर बॉय

जवाबों:


144

एक सिंगलटन एक ऐसा वर्ग है जो केवल स्वयं के एक उदाहरण को बनाने की अनुमति देता है - और उक्त उदाहरण के लिए सरल, आसान पहुंच देता है। सिंगलटन का आधार सॉफ्टवेयर डेवलपमेंट का एक पैटर्न है।

थ्रेड सुरक्षा के संबंध में कुछ अच्छी सलाह सहित - एक # # कार्यान्वयन "सिंग्लटन पैटर्न को C #" में लागू करना है जो आपको सबसे अधिक जानना चाहिए ।

ईमानदार होने के लिए, यह बहुत दुर्लभ है कि आपको एक सिंगलटन को लागू करने की आवश्यकता है - मेरी राय में यह उन चीजों में से एक होना चाहिए जिनके बारे में आपको पता होना चाहिए, भले ही इसका अक्सर उपयोग न किया जाए।


2
अच्छा ट्यूटोरियल, लेकिन पवित्र बकवास उन्होंने कोड इंडेंटेशन के लिए क्या किया
इंस्पायर

2020 में मैं इसे आदर्श कार्यान्वयन के लिए एक अधिक प्रत्यक्ष लिंक देता हूं। यह है, " .NET 4 के आलसी <टी> प्रकार का उपयोग करते हुए ", साथ ही साथ Microsoft डॉक्टर के लिए लिंक भी Lazy<T> Class
चिरमिसू

52

आपने C # मांगा। तुच्छ उदाहरण:


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

    private static readonly Singleton _singleton = new Singleton();

    public static Singleton GetSingleton()
    {
        return _singleton;
    }
}

14
थ्रेड सुरक्षित नहीं। दो धागे एक ही समय में कॉल कर सकते हैं और दो अलग-अलग ऑब्जेक्ट बना सकते हैं।
अलगेसन पलानी

5
@Alagesan पलानी, वास्तव में आप सही हैं। मैं क्लास-लेवल इनिशियलाइज़ेशन के निम्न-स्तरीय विवरणों में कुशल नहीं हूं, लेकिन मुझे लगता है कि मैंने जो बदलाव किया, वह थ्रेड-सेफ चिंता को संबोधित करता है।
क्रिस सिमंस

3
यकीन है, मैं आपको गलत नहीं इंगित कर रहा हूँ मैं थ्रेड-सेफ्टी के बारे में पाठक को संकेत दे रहा हूं, ताकि अगर उन्हें इससे निपटना पड़े तो वे सावधान रहें।
अलगेसन पलानी

9
नहीं, मुझे लगता है कि आपकी टिप्पणी महत्वपूर्ण है। यह देखते हुए कि एक सिंगलटन को एक - और केवल एक - उदाहरण देने के लिए माना जाता है, यहां दौड़ की स्थिति इस संभावना को खोलती है कि एक से अधिक वितरित किया जाए। अब संस्करण देखें, स्थैतिक क्षेत्र आरंभीकरण के साथ। मेरा मानना ​​है कि यह थ्रेड-सुरक्षा समस्या को ठीक करता है, अगर मैं डॉक्स पढ़ता हूं और यह एसओ सही ढंग से जवाब देता है।
क्रिस सीमन्स

1
@AlagesanPalani, मैं देखता हूं कि आपने कहा है कि कई अन्य उत्तर थ्रेड सुरक्षित नहीं हैं। क्या आप एक समाधान प्रदान करना चाहेंगे जो थ्रेड-सुरक्षित हो?
Bonez024

39

यह क्या है: एक वर्ग जिसके लिए बस एक ही है, एक आवेदन के जीवन भर लगातार उदाहरण है। सिंगलटन पैटर्न देखें ।

जब आपको इसका उपयोग करना चाहिए: जितना संभव हो उतना कम। केवल जब आप पूरी तरह से निश्चित हों कि आपको इसकी आवश्यकता है। मैं "कभी नहीं" कहने के लिए अनिच्छुक हूं, लेकिन आमतौर पर एक बेहतर विकल्प है, जैसे कि डिपेंडेंसी इंजेक्शन या बस एक स्थिर वर्ग।


16
मुझे यकीन नहीं है कि एक स्थिर वर्ग एक सिंगलटन से बेहतर विकल्प है ... यह वास्तव में स्थिति और भाषा पर निर्भर करता है।
marcgg

5
स्टैटिक क्लासेस एक सिंगलटन की तरह व्यवहार नहीं करते हैं, एक सिंगलटन को एक पैरामीटर के रूप में तरीकों से पारित किया जा सकता है जबकि एक स्थिर क्लास नहीं कर सकता है।
ताबिकूल

4
एग्रीक्री विथ मार्केग - मुझे स्टैटिक क्लास को सिंग्लेटन्स के अच्छे विकल्प के रूप में नहीं दिखता है, क्योंकि आपको अभी भी एक विकल्प की आपूर्ति की समस्या है, जैसे कि एक घटक के परीक्षण के दौरान जो इस वर्ग पर निर्भर करता है। लेकिन मुझे अलग-अलग उपयोग भी दिखाई देते हैं, एक स्थिर वर्ग आमतौर पर स्वतंत्र उपयोगिता कार्यों के लिए उपयोग किया जाएगा जो राज्य से स्वतंत्र हैं, जहां एक सिंगलटन एक वास्तविक वर्ग उदाहरण है, और यह आमतौर पर एक राज्य को संग्रहीत करेगा। मैं इसके बजाय DI का उपयोग करने के लिए पूरी तरह से सहमत हूं, और फिर अपने DI कंटेनर को बताऊं कि आप इसे केवल उस वर्ग के एकल उदाहरण का उपयोग करना चाहते हैं।
पीट

9
मैंने इस उत्तर को अस्वीकार कर दिया क्योंकि यह मुझे इस बारे में कोई जानकारी नहीं देता है कि इसका उपयोग कब करना है। "केवल जब आपको इसकी आवश्यकता होती है" वास्तव में मुझे किसी के लिए कोई जानकारी नहीं देता है जो एकल के लिए नया है।
सर्जियो तापिया

9
@ एडकिंस: डि डिपेंडेंसी इंजेक्शन के लिए खड़ा है, जो तब होता है जब कोई क्लास आश्रितों को (आमतौर पर) एक कंस्ट्रक्टर या सार्वजनिक संपत्ति के माध्यम से पारित किया जाता है। DI अकेले "दूरी" समस्या को हल नहीं करता है, लेकिन आमतौर पर इसे उलटा-के-नियंत्रण (IoC) कंटेनर के साथ लागू किया जाता है जो जानता है कि किसी भी निर्भरता को स्वचालित रूप से कैसे शुरू किया जाए। इसलिए यदि आप "X को पता नहीं है कि Y को कैसे खोजना / बात करना है" समस्या को हल करने के लिए एक सिंगलटन बना रहे हैं, तो DI और IoC का संयोजन एक ही समस्या को शिथिल युग्मन के साथ हल कर सकता है।
एरोन को

27

सिंग्लटन को सी # में लागू करने का एक और तरीका, मैं व्यक्तिगत रूप से इस तरह से पसंद करता हूं क्योंकि आप एक विधि के बजाय एक संपत्ति के रूप में सिंगलटन वर्ग के उदाहरण तक पहुंच सकते हैं।

public class Singleton
    {
        private static Singleton instance;

        private Singleton() { }

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

        //instance methods
    }

लेकिन अच्छी तरह से, जहां तक ​​मुझे पता है कि दोनों तरीकों को 'सही' माना जाता है, तो यह सिर्फ व्यक्तिगत स्वाद की बात है।


11
थ्रेड सुरक्षित नहीं। दो धागे एक ही समय में कॉल कर सकते हैं और दो अलग-अलग ऑब्जेक्ट बना सकते हैं।
अलगेसन पलानी

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

मैंने dofactory.com से कोड लिया , इतना फैंसी कुछ भी नहीं है लेकिन मुझे यह बहुत अच्छा लगता है उदाहरण के लिए Foo और Bar के साथ उदाहरण के अलावा C # 3.0 डिज़ाइन पैटर्न पर जूडिथ बिशप की पुस्तक मैक डॉक में सक्रिय एप्लिकेशन के बारे में उदाहरण है।

यदि आप उस कोड को देखते हैं जो हम वास्तव में लूप के लिए नई वस्तुओं का निर्माण कर रहे हैं , तो यह नई वस्तु बनाता है लेकिन उदाहरण के रूप में पुन: उपयोग करता है, जिसके परिणामस्वरूप पुराने डांसर और नवगीतकार का एक ही उदाहरण है, कैसे? फ़ंक्शन पर उपयोग किए जाने वाले स्थिर कीवर्ड के कारण GetLoadBalancer () , अलग-अलग सर्वर मान होने के बावजूद, जो कि यादृच्छिक सूची है, GetLoadBalancer () पर स्थिर एक विशिष्ट वस्तु के बजाय स्वयं के प्रकार के अंतर्गत आता है।

इसके अतिरिक्त यहां डबल चेक लॉकिंग है

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

MSDN के बाद से

लॉक कीवर्ड यह सुनिश्चित करता है कि एक धागा कोड के एक महत्वपूर्ण खंड में प्रवेश नहीं करता है, जबकि दूसरा धागा महत्वपूर्ण अनुभाग में है। यदि कोई अन्य थ्रेड लॉक किए गए कोड को दर्ज करने का प्रयास करता है, तो वह तब तक प्रतीक्षा करेगा, जब तक कि ऑब्जेक्ट जारी नहीं हो जाता।

इसलिए हर बार आपसी-बहिष्करण लॉक जारी किया जाता है, भले ही इसकी आवश्यकता न हो, क्योंकि यह अनावश्यक है इसलिए हमारे पास शून्य चेक है।

उम्मीद है कि यह और अधिक साफ करने में मदद करता है।

और कृपया टिप्पणी करें कि क्या मेरी समझ गलत तरीकों को निर्देशित कर रही है।


6

एक सिंगलटन (और यह सी # से बंधा नहीं है, यह एक ओओ डिजाइन पैटर्न है) जब आप अपने आवेदन के दौरान कक्षा के केवल एक उदाहरण को बनाने की अनुमति देना चाहते हैं। यूजेज में आमतौर पर वैश्विक संसाधन शामिल होंगे, हालांकि मैं व्यक्तिगत अनुभव से कहूंगा, वे बहुत दर्द का स्रोत हैं।


5

जब तक केवल एक सिंगलटन का एक उदाहरण हो सकता है, यह एक स्थिर वर्ग के समान नहीं है। एक स्थिर वर्ग में केवल स्थैतिक विधियां हो सकती हैं और उनका कभी भी त्वरित रूप से उपयोग नहीं किया जा सकता है, जबकि किसी एकल वस्तु के उदाहरण का उपयोग किसी अन्य वस्तु की तरह ही किया जा सकता है।


2

यह एक डिज़ाइन पैटर्न है और यह c # के लिए विशिष्ट नहीं है। इस विकिपीडिया लेख पर इंटरनेट और एसओ की तरह, इसके बारे में अधिक ।

सॉफ्टवेयर इंजीनियरिंग में, सिंगलटन पैटर्न एक डिज़ाइन पैटर्न है जिसका उपयोग किसी कक्षा के एक वस्तु में एक पल की रोक को प्रतिबंधित करने के लिए किया जाता है। यह उपयोगी है जब सिस्टम में क्रियाओं के समन्वय के लिए एक वस्तु की आवश्यकता होती है। अवधारणा को कभी-कभी उन प्रणालियों के लिए सामान्यीकृत किया जाता है जो केवल एक वस्तु के मौजूद होने पर अधिक कुशलता से संचालित होती हैं, या जो तात्कालिकता को एक निश्चित संख्या में वस्तुओं तक सीमित कर देती है (जैसे, पांच)। कुछ इसे एक विरोधी पैटर्न मानते हैं, यह देखते हुए कि यह अति प्रयोग किया जाता है, उन परिस्थितियों में अनावश्यक सीमाओं का परिचय देता है जहां एक वर्ग का एकमात्र उदाहरण वास्तव में आवश्यक नहीं है, और एक आवेदन में वैश्विक स्थिति का परिचय देता है।

आपको इसका उपयोग करना चाहिए यदि आप एक ऐसा वर्ग चाहते हैं जो केवल एक बार ही संस्थापित हो सके।


2

मैं इसे लुकअप डेटा के लिए उपयोग करता हूं। 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

एक सिंगलटन क्या है:
यह एक ऐसा वर्ग है जो केवल स्वयं के एक उदाहरण को बनाने की अनुमति देता है, और आमतौर पर उस उदाहरण तक सरल पहुंच देता है।

आपको कब उपयोग करना चाहिए:
यह स्थिति पर निर्भर करता है।

नोट: कृपया db कनेक्शन पर उपयोग न करें, विस्तृत उत्तर के लिए कृपया @Chad अनुदान के उत्तर को देखें

यहाँ एक सरल उदाहरण है 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;
        }
    }
}

आप Lazy<T>अपने बनाने के लिए भी उपयोग कर सकते हैं Singleton

उपयोग करने वाले अधिक विस्तृत उदाहरण के लिए यहां देखेंLazy<T>


1

यहाँ क्या सिंगलटन है: http://en.wikipedia.org/wiki/Singleton_pattern

मैं C # नहीं जानता, लेकिन यह वास्तव में सभी भाषाओं में समान है, केवल कार्यान्वयन अलग है।

जब संभव हो तो आपको आमतौर पर सिंगलटन से बचना चाहिए, लेकिन कुछ स्थितियों में यह बहुत सुविधाजनक है।

मेरी अंग्रेजी के लिए खेद है ;)


आपकी अंग्रेजी ठीक है :)
FrenkyB

1

पूरे एप्लिकेशन डोमेन के लिए एकल उदाहरण बनाने के लिए सिंगलटन क्लास का उपयोग किया जाता है।

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

में इस लेख में यह वर्णन किया गया है कि किस प्रकार हम केवल पढ़ने के लिए चर और अनुप्रयोगों में उनके व्यावहारिक उपयोग का उपयोग कर धागा सुरक्षित सिंगलटन वर्ग बना सकते हैं।


1

मुझे पता है कि इस सवाल का जवाब देने में बहुत देर हो चुकी है लेकिन ऑटो-प्रॉपर्टी के साथ आप ऐसा कुछ कर सकते हैं:

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

Singletonआप कहां हैं कक्षा है और इसके माध्यम से हो सकता है, इस मामले में आसानी से संपत्ति Instance


0

EX आप उन वैश्विक सूचनाओं के लिए सिंगलटन का उपयोग कर सकते हैं जिन्हें इंजेक्ट करने की आवश्यकता है।

मेरे मामले में, मैं ग्लोबल स्टेटिक क्लास में लॉग इन यूजर डिटेल (उपयोगकर्ता नाम, अनुमति आदि) रख रहा था। और जब मैंने यूनिट टेस्ट को लागू करने की कोशिश की, तो कोई तरीका नहीं था कि मैं नियंत्रक कक्षाओं में निर्भरता को इंजेक्ट कर सकूं। इस प्रकार मैंने अपनी स्टेटिक क्लास को सिंगलटन पैटर्न में बदल दिया है।

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

हमें C # में सिंगलटन डिज़ाइन पैटर्न का उपयोग करने की आवश्यकता है, जब हमें यह सुनिश्चित करने की आवश्यकता है कि किसी विशेष वर्ग का केवल एक ही उदाहरण बनने जा रहा है और फिर पूरे एप्लिकेशन के लिए उस उदाहरण पर सरल वैश्विक पहुँच प्रदान करें।

वास्तविक समय परिदृश्य जहां आप सिंगलटन डिज़ाइन पैटर्न का उपयोग कर सकते हैं: सेवा प्रॉक्सी: जैसा कि हम जानते हैं कि सेवा एपीआई को लागू करना एक आवेदन में एक व्यापक ऑपरेशन है। सेवा API को इनवॉइस करने के लिए अधिकांश समय लेने वाली प्रक्रिया सेवा क्लाइंट बना रही है। यदि आप सर्विस प्रॉक्सी को सिंगलटन बनाते हैं तो यह आपके आवेदन के प्रदर्शन में सुधार करेगा।

Facades: आप सिंगलटन के रूप में डेटाबेस कनेक्शन भी बना सकते हैं जो एप्लिकेशन के प्रदर्शन में सुधार कर सकता है।

लॉग: एक आवेदन में, एक फ़ाइल पर I / O ऑपरेशन करना एक महंगा ऑपरेशन है। यदि आप आपको लॉगर को सिंगलटन बनाते हैं तो यह I / O ऑपरेशन के प्रदर्शन में सुधार करेगा।

डेटा शेयरिंग: यदि आपके पास कोई निरंतर मान या कॉन्फ़िगरेशन मान है तो आप इन मूल्यों को सिंगलटन में रख सकते हैं ताकि इन्हें एप्लिकेशन के अन्य घटकों द्वारा पढ़ा जा सके।

कैशिंग: जैसा कि हम जानते हैं कि डेटाबेस से डेटा प्राप्त करना एक समय लेने वाली प्रक्रिया है। अपने आवेदन में, आप मास्टर और कॉन्फ़िगरेशन को मेमोरी में कैश कर सकते हैं जो डीबी कॉल से बचेंगे। ऐसी स्थितियों में, सिंगलटन क्लास का उपयोग थ्रेड सिंक्रोनाइज़ेशन के साथ एक कुशल तरीके से कैशिंग को संभालने के लिए किया जा सकता है जो कि एप्लिकेशन के प्रदर्शन में काफी सुधार करता है।

C # में सिंगलटन डिजाइन पैटर्न के नुकसान # C में सिंगलटन डिजाइन पैटर्न का उपयोग करने के नुकसान इस प्रकार हैं:

यूनिट परीक्षण बहुत मुश्किल है क्योंकि यह एक वैश्विक राज्य को एक आवेदन में पेश करता है। यह एक कार्यक्रम के भीतर समानता की क्षमता को कम करता है क्योंकि एकल-थ्रेडेड वातावरण में सिंगलटन उदाहरण तक पहुंचने के लिए, आपको लॉकिंग का उपयोग करके ऑब्जेक्ट को क्रमबद्ध करना होगा।

मैंने इसे निम्नलिखित लेख से लिया है।

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


0

थ्रेड्स का उपयोग किए बिना थ्रेड सेफ सिंगलटन और कोई आलसी इंस्टेंटेशन नहीं।

इस कार्यान्वयन में एक स्थिर रचनाकार है, इसलिए यह केवल एक बार एप्लिकेशन डोमेन के अनुसार निष्पादित होता है।

public sealed class Singleton
{

    static Singleton(){}

    private Singleton(){}

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

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.