खोज…


स्टेटिकली इनिशियलाइज़्ड सिंगलटन

public class Singleton
{
    private readonly static Singleton instance = new Singleton();
    private Singleton() { }
    public static Singleton Instance => instance;
}

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

म्यूटिंग instance एक थ्रेड-सुरक्षित ऑपरेशन नहीं है, इसलिए प्रारंभ के बाद आसानी से readonly विशेषता अपरिवर्तनीयता की गारंटी देती है।

आलसी, धागा-सुरक्षित सिंगलटन (डबल चेक्ड लॉकिंग का उपयोग करके)

एक सिंगलटन का यह थ्रेड-सुरक्षित संस्करण .NET के शुरुआती संस्करणों में आवश्यक था जहां static इनिशियलाइज़ेशन को थ्रेड-सुरक्षित होने की गारंटी नहीं थी। फ्रेमवर्क के अधिक आधुनिक संस्करणों में एक स्टेटिकली इनिशियलाइज्ड सिंगलटन को आमतौर पर पसंद किया जाता है क्योंकि निम्नलिखित पैटर्न में कार्यान्वयन गलतियों को करना बहुत आसान है।

public sealed class ThreadSafeSingleton
{
   private static volatile ThreadSafeSingleton instance;
   private static object lockObject = new Object();

   private ThreadSafeSingleton()
   {
   }

   public static ThreadSafeSingleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (lockObject) 
            {
               if (instance == null)
               {
                  instance = new ThreadSafeSingleton();
               }
            }
         }

         return instance;
      }
   }
}

ध्यान दें कि if (instance == null) चेक दो बार किया जाता है: एक बार लॉक हासिल करने से पहले, और एक बार बाद में। यह कार्यान्वयन अभी भी पहली अशक्त जाँच के बिना थ्रेड-सुरक्षित होगा। हालांकि, इसका मतलब यह होगा कि उदाहरण के अनुरोध के बाद हर बार एक लॉक हासिल किया जाएगा, और इससे प्रदर्शन को नुकसान होगा। पहला नल चेक जोड़ा जाता है ताकि लॉक को तब तक अधिग्रहित न किया जाए जब तक कि यह आवश्यक न हो। दूसरा अशक्त जांच सुनिश्चित करता है कि केवल ताला प्राप्त करने के लिए पहला धागा तो उदाहरण बनाता है। अन्य थ्रेड्स को पॉप्युलेट होने और आगे निकलने के लिए उदाहरण मिलेगा।

आलसी, धागा-सुरक्षित सिंगलटन (आलसी का उपयोग करके) )

.Net 4.0 प्रकार आलसी थ्रेड-सेफ ऑब्जेक्ट इनिशियलाइज़ेशन की गारंटी देता है, इसलिए इस प्रकार का उपयोग सिंग्लेटन्स बनाने के लिए किया जा सकता है।

public class LazySingleton
{
    private static readonly Lazy<LazySingleton> _instance =
        new Lazy<LazySingleton>(() => new LazySingleton());
 
    public static LazySingleton Instance
    {
        get { return _instance.Value; }
    }

    private LazySingleton() { }
}

Lazy<T> का उपयोग करना सुनिश्चित करेगा कि ऑब्जेक्ट केवल तभी त्वरित हो जब उसका उपयोग कॉलिंग कोड में कहीं किया जाए।

एक साधारण उपयोग की तरह होगा:

using System;
                    
public class Program
{
    public static void Main()
    {
        var instance = LazySingleton.Instance;
    }
}

.NET फिडल पर लाइव डेमो

आलसी, धागा सुरक्षित सिंगलटन (.NET 3.5 या पुराने के लिए, वैकल्पिक कार्यान्वयन)

.NET 3.5 और पुराने में आपके पास Lazy<T> वर्ग नहीं होने के कारण आप निम्न पैटर्न का उपयोग करते हैं:

public class Singleton
{
    private Singleton() // prevents public instantiation
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }
    
    private class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

यह जॉन स्कीट के ब्लॉग पोस्ट से प्रेरित है।

चूँकि Nested क्लास नेस्टेड है और निजी तौर पर सिंगलटन Sigleton का Sigleton क्लास के अन्य सदस्यों (जैसे सार्वजनिक रूप से प्रॉपर्टी, उदाहरण के लिए) को एक्सेस करने से शुरू नहीं होगा।

सिंग्लटन उदाहरण का निपटान जब इसकी आवश्यकता नहीं रह जाती है

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

public class LazySingleton : IDisposable
{
    private static volatile Lazy<LazySingleton> _instance;
    private static volatile int _instanceCount = 0;
    private bool _alreadyDisposed = false;

public static LazySingleton Instance
{
    get
    {
        if (_instance == null)
            _instance = new Lazy<LazySingleton>(() => new LazySingleton());
        _instanceCount++;
        return _instance.Value;
    }
}

private LazySingleton() { }

// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{ 
    if (--_instanceCount == 0) // No more references to this object.
    {       
       Dispose(true);
       GC.SuppressFinalize(this);           
    }
}

// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
    if (_alreadyDisposed) return; 
  
    if (disposing) 
    {
        _instance = null; // Allow GC to dispose of this instance.
        // Free any other managed objects here.
    }
  
    // Free any unmanaged objects here.
    _alreadyDisposed = true;
}

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

public class Program
{
    public static void Main()
    {
        using (var instance = LazySingleton.Instance)
        {
            // Do work with instance
        }
    }
}

कृपया ध्यान दें कि यह उदाहरण थ्रेड-सुरक्षित नहीं है



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow