स्थिर रचनाकारों के लिए कई नुकसान हैं। उदाहरण के लिए, यदि एक स्थिर कन्स्ट्रक्टर throws an exception, तो आप TypeInitializationException
प्राप्त करना जारी रखेंगे जब भी आप इसके किसी भी सदस्य तक पहुंचते हैं।
यदि कोई स्थिर कंस्ट्रक्टर अपवाद फेंकता है, तो रनटाइम इसे दूसरी बार नहीं बुलाएगा, और यह एप्लीकेशन उस एप्लिकेशन डोमेन के जीवनकाल के लिए अनियंत्रित रहेगा जिसमें आपका प्रोग्राम चल रहा है।
सामान्य रूप से, स्थिर वर्गों का उपयोग केवल स्टेटलेस परिदृश्यों में किया जाना चाहिए जहां आपको किसी भी प्रारंभिकरण की आवश्यकता नहीं होगी।
public class MyClass
{
private static readonly Lazy<MyClass> current =
new Lazy<MyClass>(() => new MyClass());
public static MyClass Current
{
get { return current.Value; }
}
private MyClass()
{
// Initialization goes here.
}
public void Foo()
{
// ...
}
public void Bar()
{
// ...
}
}
static void Main(string[] args)
{
MyClass.Current.Foo(); // Initialization only performed here.
MyClass.Current.Bar();
MyClass.Current.Foo();
}
संपादित:: आपकी कक्षा प्रारंभ करने की आवश्यकता है, तो आप singleton pattern, का उपयोग कर से बेहतर है जो पहले उपयोग पर lazily initialized हो सकता है हो सकता है मैं कुछ आगे बात पर पढ़ने किया था, और यह प्रतीत होता है कि स्थैतिक रचनाकार यदि आप ब्लॉकिंग ऑपरेशंस (जैसे एसिंक्रोनस कॉलबैक या थ्रेड सिंक्रनाइज़ेशन) करते हैं तो डेडलॉक्स का कारण बनते हैं।
सीएलआर आंतरिक रूप से प्रकार प्रारंभकर्ताओं (स्थिर रचनाकारों) को कई बार निष्पादित करने से रोकने के लिए लॉकिंग का उपयोग करता है। इस प्रकार, यदि आपका स्थिर कन्स्ट्रक्टर किसी दूसरे धागे से अपने घोषित प्रकार के किसी अन्य सदस्य तक पहुंचने का प्रयास करता है, तो यह अनिवार्य रूप से डेडलॉक होगा। चूंकि "दूसरा सदस्य" एक पिनिंगक्यू या टीपीएल ऑपरेशन के हिस्से के रूप में घोषित एक अज्ञात फ़ंक्शन हो सकता है, इसलिए ये बग सूक्ष्म और पहचानने में कठोर हो सकती हैं।
इगोर Ostrovsky (MSFT) अपने Static constructor deadlocks लेख में इस बताते हैं, एक गतिरोध की निम्न उदाहरण प्रदान:
using System.Threading;
class MyClass
{
static void Main() { /* Won’t run... the static constructor deadlocks */ }
static MyClass()
{
Thread thread = new Thread(arg => { });
thread.Start();
thread.Join();
}
}
उपरोक्त उदाहरण में, नया थ्रेड खाली गुमनाम समारोह, { }
का उपयोग करने की जरूरत है, परिभाषित इसके कॉलबैक के रूप में। हालांकि, चूंकि अज्ञात फ़ंक्शन को दृश्यों के पीछे MyClass
की दूसरी निजी विधि के रूप में संकलित किया गया है, इसलिए नया थ्रेड MyClass
प्रकार प्रारंभ होने से पहले इसका उपयोग नहीं कर सकता है। और, चूंकि MyClass
स्थिर कन्स्ट्रक्टर को नए थ्रेड को पहले पूरा करने की प्रतीक्षा करनी है (thread.Join()
की वजह से), एक डेडलॉक आ जाता है।
क्या निर्माता के अंदर अपवादों के अलावा कुछ और है? उदाहरण के लिए, मैं "डेडलॉक" की व्याख्या कैसे कर सकता हूं जैसे परिदृश्य मैं अनुभव कर रहा हूं? क्या दृश्यों के पीछे किसी भी प्रकार स्थिर प्रकारों से जुड़ा कोई लॉकिंग है? –
@liortal: ऊपर उत्तर दिया गया। – Douglas
क्या आपके पहले उदाहरण में और इन लाइनों के बीच क्या कोई अंतर है? 'निजी स्थिर रीडोनली आलसी वर्तमान; स्थैतिक MyClass {वर्तमान = नया आलसी (() => नया MyClass()); } ' (क्षमा करें प्रपत्रण सही नहीं लग रहा है :)) –
Mark