C# Language
सिंगलटन कार्यान्वयन
खोज…
स्टेटिकली इनिशियलाइज़्ड सिंगलटन
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 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
}
}
}
कृपया ध्यान दें कि यह उदाहरण थ्रेड-सुरक्षित नहीं है ।