एक स्थिर रचनाकार कैसे काम करता है?


82
namespace MyNameSpace
{
    static class MyClass
    {
        static MyClass()
        {
            //Authentication process.. User needs to enter password
        }

        public static void MyMethod()
        {
            //Depends on successful completion of constructor
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.MyMethod();
        }
    }
}

यहां वह क्रम है जो मैंने ग्रहण किया

  1. स्टैटिक कंस्ट्रक्टर की शुरुआत
  2. स्थिर निर्माणकर्ता का अंत
  3. मुख्य की शुरुआत
  4. MyMethod की शुरुआत
  5. मुख्य का अंत

अब किसी भी परिदृश्य में यदि 4 2 से पहले शुरू हो जाएगा तो मुझे खराब कर दिया जाएगा। क्या यह संभव है?


8
क्या यह एक जावा या सी # सवाल है? आपने दोनों टैग लगाए हैं, और मुझे नहीं लगता कि विनिर्देश दो भाषाओं में समान हैं।
ARRG

मेरे खुलेपन में यह दोनों के लिए समान है .. लेकिन मैं C # आदमी हूं .. इसके लिए Sry
om471987

4
जावा में स्थिर निर्माणकर्ता नहीं है, स्थिर स्थैतिककरण के लिए सिर्फ स्थिर ब्लॉक। स्थैतिक {// कुछ करो ...}
deraj

2
व्यक्तिगत रूप से, मैं एक स्थिर कंस्ट्रक्टर के अंदर किसी भी प्रकार की अन्तरक्रियाशीलता से असहज महसूस करता हूँ। मैं आपके लक्ष्य को समझता हूं (इस स्थिर वर्ग में प्रत्येक विधि को तब तक प्रतीक्षा करें जब तक कि उपयोगकर्ता इसे चलाने की अनुमति देने से पहले अधिकृत न हो), लेकिन वास्तव में इसे पूरा करने की इस पद्धति को नापसंद करते हैं।
ब्रायन

@ ब्रायन: - हाँ ... आप सही कह रहे हैं ... मैं सिर्फ विश्लेषण कर रहा था .. अंत में मैंने सिर्फ कंस्ट्रक्टर का उपयोग नहीं करने का फैसला किया लेकिन प्रारंभिक विधि
om471987

जवाबों:


220

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

यहां वह क्रम है जो मैंने ग्रहण किया

  1. क्लास कंस्ट्रक्टर की शुरुआत (जिसे भी जाना जाता है cctor)
  2. ट्रैक्टर का अंत
  3. मेन की शुरुआत
  4. MyMethod की शुरुआत

क्या ये सही है?

सही अनुक्रम है:

  1. कार्यक्रम के लिए ट्रैक्टर की शुरुआत, अगर वहाँ एक है। वहाँ नही है।
  2. कार्यक्रम के लिए ट्रैक्टर का अंत, अगर वहाँ एक है। वहाँ नही है।
  3. मेन की शुरुआत
  4. MyClass के लिए ट्रैक्टर की शुरुआत
  5. MyClass के लिए ट्रैक्टर का अंत
  6. MyClass.MyMethod की शुरुआत

यदि कोई स्थैतिक क्षेत्र आरम्भिक है तो क्या होगा?

सीएलआर को उस क्रम को बदलने की अनुमति दी जाती है जिसमें कुछ मामलों में स्थैतिक क्षेत्र के आरंभकर्ता चलते हैं। विवरण के लिए विषय पर जॉन का पृष्ठ देखें:

स्थिर कन्स्ट्रक्टर और टाइप इनिशियलाइज़र के बीच अंतर

क्या किसी स्थिर विधि के लिए यह संभव MyMethodहै कि उस वर्ग के ट्रैक्टर को पूरा करने से पहले बुलाया जाए?

हाँ। यदि ट्रैक्टर खुद ही MyMethod कहता है, तो जाहिर है कि MyMethod को ट्रैक्टर पूरा होने से पहले बुलाया जाएगा।

ट्रैक्टर को MyMethod नहीं कहते हैं। क्या MyMethodमायक्लास के पूरा होने से पहले कभी भी स्थैतिक विधि को बुलाया जाना संभव है ?

हाँ। यदि ट्रैक्टर दूसरे प्रकार का उपयोग करता है, जिसका ट्रैक्टर MyMethod कहता है, तो MyMassod को MyClass ट्रैक्टर पूर्ण होने से पहले बुलाया जाएगा।

कोई भी डॉक्टर MyMethod को प्रत्यक्ष या अप्रत्यक्ष रूप से नहीं कहता है! अब क्या यह संभव है MyMethodकि माईक्लास के ट्रैक्टर के पूर्ण होने से पहले एक स्थैतिक विधि को बुलाया जाए?

नहीं।

क्या यह अभी भी सच है अगर कई धागे शामिल हैं?

हाँ। किसी भी धागे पर स्थिर विधि को बुलाया जा सकता है इससे पहले कि ट्रैक्टर एक धागे पर खत्म हो जाएगा।

क्या ट्रैक्टर को एक से अधिक बार कहा जा सकता है? मान लीजिए कि दो धागों से दोनों ट्रैक्टर चलते हैं।

ट्रैक्टर को एक बार में बुलाया जाना चाहिए, चाहे कितने भी धागे शामिल हों। यदि दो धागे MyMethod को "एक ही समय में" कहते हैं, तो वे दौड़ते हैं। उनमें से एक दौड़ और ब्लॉक खो देता है जब तक कि MyClass cctor विजेता धागे पर पूरा नहीं हो जाता।

हारने वाले धागे ब्लॉक तब तक होते हैं जब तक कि ट्रैक्टर नहीं किया जाता है? सच में ?

वास्तव में।

तो क्या होगा अगर जीतने वाले थ्रेड पर मौजूद कोड हारने वाले धागे द्वारा लिए गए लॉक को ब्लॉक करता है ?

फिर आपके पास एक क्लासिक लॉक ऑर्डर उलटा स्थिति है। आपका कार्यक्रम गतिरोध सदैव।

जो खतरनाक लगता है। मैं गतिरोध से कैसे बच सकता हूं?

अगर ऐसा करते समय आपको दर्द होता है तो ऐसा करना बंद कर देंकभी भी ऐसा कुछ न करें जो एक ट्रैक्टर में अवरुद्ध हो सकता है।

क्या जटिल सुरक्षा आवश्यकताओं को लागू करने के लिए ट्रैक्टर आरंभीकरण शब्दार्थ पर भरोसा करना एक अच्छा विचार है? और क्या यह एक अच्छा विचार है कि एक ट्रैक्टर है जो उपयोगकर्ता को बातचीत करता है?

न ही अच्छे विचार हैं। मेरी सलाह यह है कि आपको यह सुनिश्चित करने के लिए एक अलग तरीका खोजना चाहिए कि आपके तरीकों के सुरक्षा-प्रभाव वाले पूर्व शर्त पूरे किए जाएं।


5
एरिक, मैं उत्सुक हूं कि आपने इस उत्तर में "क्लास कंस्ट्रक्टर" या "ट्रैक्टर" के साथ "स्थिर कंस्ट्रक्टर" क्यों बदल दिया। क्या यह एक ट्रैक्टर का जिक्र करते समय "स्थिर कंस्ट्रक्टर" का उपयोग करने के लिए अनुचित है?
21

6
@ एफोग: मैं शब्दावली के मेरे उपयोग में लगातार रहना चाहता था, इसलिए मैंने सबसे छोटा चुना। "स्टेटिक कंस्ट्रक्टर" और "क्लास कंस्ट्रक्टर" दोनों ठीक हैं। कार्यान्वयन विस्तार के रूप में, एक प्रकार के स्थिर निर्माता को ".cctor" नामक एक विशेष विधि के रूप में उत्सर्जित किया जाता है, इसलिए इस तरह के निर्माणकर्ता को "एक ट्रैक्टर" के रूप में संदर्भित करना आम है। क्या मैं एक अधिक औपचारिक संदर्भ में लिख रहा था, मैं एक लंबे शब्दों का उपयोग करूंगा।
एरिक लिपर्ट

@ EricLippert क्या स्थैतिक निर्माता के साथ गैर-स्थिर वर्गों के लिए भी यह सही है?
महापुरूष

2
@Legends: क्या यह स्थैतिक निर्माता के साथ गैर-स्थिर वर्गों के लिए भी सही है? हाँ।
एरिक लिपर्ट

24

MSDN के अनुसार , एक स्थिर निर्माता:

किसी स्थिर निर्माता को पहली आवृत्ति के बनने से पहले या किसी भी स्थिर सदस्य को संदर्भित करने से पहले वर्ग को प्रारंभ करने के लिए स्वचालित रूप से कहा जाता है।

तो स्थिर निर्माता से पहले स्थिर विधि बुलाया जाएगा MyClass.MyMethod()शुरू हो जाती है (यह मानते हुए नहीं भी स्थिर निर्माण या निश्चित रूप से स्थिर क्षेत्र आरंभीकरण के दौरान लागू)।

अब, यदि आप उस में कुछ भी अतुल्यकालिक कर रहे हैं static constructor, तो यह आपका काम है कि उसे सिंक्रोनाइज़ करना है।


7
यदि आप कुछ भी अतुल्यकालिक कर रहे हैं जिसमें एक स्थिर निर्माणकर्ता में दूसरा धागा शामिल है, तो आप दर्द की दुनिया के लिए हैं । कुछ भी गतिरोध तेज नहीं करता है। उदाहरण के लिए stackoverflow.com/a/8883117/88656 देखें ।
एरिक लिपर्ट

@ एरिक: सहमत ... मैं ऐसा नहीं करना चाहूंगा, लेकिन यह सुनिश्चित नहीं कर पाया कि माईमिथोड द्वारा बुलाए जाने के समय वह वास्तव में क्या करना चाहता था ...
जेम्स माइकल हरे

11

# 3 वास्तव में # 1 है: स्थैतिक आरंभीकरण तब तक शुरू नहीं होता है जब तक कि वह जिस वर्ग का है, उसका पहला उपयोग शुरू नहीं होता है।

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


एक नोट के रूप में, यह मेरी समझ है कि staticअनुकूलन के लिए पात्रता के आधार पर प्रारंभिक उपयोग को वास्तव में पहले कहा जा सकता है।
जेम्स माइकल हरे


1
एक स्थिर रचनाकार के लिए, सच है, लेकिन स्थैतिक आरंभ के लिए मेरी बात थी। क्षमा करें, शायद मैं सिर्फ 'स्थैतिक आरंभीकरण शुरू नहीं होता है' वाक्यांश पर निट्स चुन रहा था ... यह स्थैतिक निर्माण के लिए सही है, लेकिन यह नहीं कि यदि क्लास में स्थिर कंस्ट्रक्टर नहीं है, तो स्टैटिक इनिशियलाइज़ेशन पहले भी हो सकता है।
जेम्स माइकल हरे

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

@ नाम: आप अतिव्यापी नहीं हैं - शब्दावली यहाँ महत्वपूर्ण अंतर है। स्टेटिक कंस्ट्रक्टर एक C # कॉन्सेप्ट हैं, जबकि टाइप इनिशियलाइज़ेशन एक .NET चीज़ है। स्टैटिक कंस्ट्रक्टर (C #) के अंदर का कोड टाइप इनिशियलाइज़र (.NET) का हिस्सा बन जाता है, लेकिन जब और कैसे इनिशियल ट्रिगर्स (यानी, beforefieldinitशब्दार्थ) ट्रिगर होता है, तो यह निर्धारित किया जाता है कि C # क्लास में स्टैटिक कंस्ट्रक्टर है या नहीं।
ल्यूक

9

से प्रलेखन (जोर मेरा):

एक स्थिर निर्माता वर्ग प्रारंभ करने में स्वचालित रूप से कहा जाता है से पहले पहले उदाहरण बनाई गई है या किसी स्थिर सदस्यों संदर्भित


2

आप गारंटी दे सकते हैं कि 4 हमेशा 2 के बाद आएगा (यदि आप अपने स्टैटिक विधि से अपनी कक्षा का एक उदाहरण नहीं बनाते हैं), हालांकि यह 1 और 3 के लिए सही नहीं है।


2

माइमेथोड निष्पादित होने से पहले स्थिर निर्माणकर्ता को बुलाया जाएगा। हालाँकि यदि आपको खराब कर दिया जाता है यदि 4 को 2 से पहले बुलाया जाता है तो मैं आपको सुझाव देता हूं कि आप अपने डिज़ाइन पर फिर से विचार करें। वैसे भी स्टैटिक कंस्ट्रक्टर में जटिल चीजें नहीं करनी चाहिए।


2

CLR इस बात की गारंटी देता है कि किसी स्थिर सदस्य के पहुँचने से पहले स्थिर निर्माणकर्ता चलता है। हालाँकि, आपका डिज़ाइन थोड़ा बदबूदार है। इस तरह से कुछ करना अधिक सरल होगा:

static void Main(string[] args) 
{ 
     bool userIsAuthenticated = MyClass.AuthenticateUser();
     if (userIsAuthenticated)
         MyClass.MyMethod(); 
 } 

आपके डिज़ाइन के साथ, यदि प्रमाणीकरण विफल रहता है, तो MyMethod को चलने से रोकने का एकमात्र तरीका अपवाद फेंकना है।


2

यह सुनिश्चित किया जाता है कि किसी भी विधि को निष्पादित करने से पहले एक स्थिर वर्ग के निर्माता को बुलाया गया है। उदाहरण:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Press enter");
        Console.ReadLine();
        Boop.SayHi();
        Boop.SayHi();
        Console.ReadLine();
    }

}

static class Boop
{
    static Boop()
    {
        Console.WriteLine("Hi incoming ...");
    }

    public static void SayHi()
    {
        Console.WriteLine("Hi there!");
    }
}

आउटपुट:

एंटर दबाए

// एंटर दबाने के बाद

हाय आने वाली ...

नमस्ते!

नमस्ते!


सिस्टम का उपयोग कर; नामस्थान MyNameSpace {क्लास प्रोग्राम {स्टेटिक शून्य मेन (स्ट्रिंग [] args) {Console.WriteLine ("मुख्य में दर्ज किया गया"); Boop.SayHi (); Boop.SayHi (); }} स्थिर वर्ग Boop {स्थैतिक Boop () {Console.Read (); Console.WriteLine ("कंस्ट्रक्टर कुंजी दर्ज की गई"); } public static void SayHi () {Console.WriteLine ("विधि कहा जाता है"); }}} हाँ, यह कार्यक्रम बेहतर समझ देता है
om471987

संभवतः। अगली बार इसे उत्तर के रूप में पोस्ट करें, हालांकि। यह तब अधिक उपयोगी और दृश्यमान है।
हयियू

1

यहां वास्तविक क्रम है जिसमें चीजें नीचे जाती हैं:

  1. की शुरुआत Main
  2. स्टैटिक MyClassकंस्ट्रक्टर की शुरुआत
  3. स्थिर MyClassकंस्ट्रक्टर का अंत
  4. की शुरुआत MyMethod
  5. का अंत Main

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