एक उदाहरण पर विचार करें:

class Test {

    string S { get; set; }

    public Test() {
        Init();
    }

    private void Init() {
        S = "hello";
    }
 
}

निरर्थक C# प्रोजेक्ट फीचर का उपयोग करते हुए, यह नमूना एक कंपाइलर चेतावनी को ट्रिगर करेगा:

चेतावनी CS8618 गैर-अशक्त संपत्ति 'S' में कंस्ट्रक्टर से बाहर निकलने पर एक गैर-शून्य मान होना चाहिए। संपत्ति को अशक्त घोषित करने पर विचार करें।

हालांकि, कंस्ट्रक्टर से बाहर निकलने पर संपत्ति में गैर-शून्य मान होता है, यह सीधे कंस्ट्रक्टर में सेट नहीं होता है, बल्कि परोक्ष रूप से एक ऐसी विधि में होता है जिसे कंस्ट्रक्टर से बिना शर्त कहा जाता है।

यह उदाहरण स्पष्ट रूप से दिखाता है कि S संपत्ति के कभी भी शून्य होने की कोई संभावना नहीं है। जब Test वर्ग का एक उदाहरण बनाया जाता है, तो Init() विधि को बिना शर्त कहा जाता है, इसलिए S गुण हमेशा "हैलो" पर सेट होता है।

बेशक इस चेतावनी को कोड में दबाया जा सकता है, लेकिन यह सिर्फ भद्दा दिखता है। क्या यह संकलक को बताने का एक बेहतर तरीका है कि मैंने वास्तव में S संपत्ति को गैर-शून्य मान पर कहीं और सेट किया है?

BTW, यदि आप वास्तव में आश्चर्य करते हैं कि अप्रत्यक्ष रूप से कंस्ट्रक्टर में मान क्यों सेट करें, तो मान लें कि Derived प्रकार की एक और व्युत्पन्न संपत्ति D है। Derived का एक उदाहरण बनाने के लिए स्ट्रिंग को पहले पार्स किया जाना चाहिए और जब भी हम D प्रॉपर्टी पढ़ते हैं तो हम स्ट्रिंग को पार्स नहीं करना चाहते हैं।

तो, अधिक यथार्थवादी कोड इस तरह दिखेगा:

class Test {

    public string S { 
        get => _S;
        set => D = new Derived(_S = value);
    }

    public Derived D { get; private set; }

    public Test(string s) => D = new Derived(_S = s);

    private string _S;
 
}

जैसा कि आप देख सकते हैं, कंस्ट्रक्टर से बाहर निकलने पर S और D दोनों गैर-शून्य मान पर सेट होते हैं। फिर भी कोड अभी भी संकलक चेतावनी CS8618 को ट्रिगर करता है।

3
Harry 22 नवम्बर 2021, 17:41
अच्छा प्रश्न और उत्तर आपके पहले उदाहरण का सही समाधान है। हालांकि, आपका 'अधिक यथार्थवादी' कोड कोई त्रुटि उत्पन्न नहीं करेगा - _S है कंस्ट्रक्टर में सेट है। S स्वयं को सेट करने की आवश्यकता नहीं है क्योंकि इसका गेटर कुछ गैर-शून्य देता है।
 – 
Charles Mager
22 नवम्बर 2021, 17:53
आपके अन्य प्रश्न के लिए, मैं अपने उत्तर में नहीं जोड़ता क्योंकि मुझे यकीन नहीं है कि मैं सही हूं, अगर कोई गलत है तो कृपया सही करें। S मान सेट करने के लिए किसी अन्य विधि का उपयोग करने के आपके इरादे को जानने के लिए कंपाइलर उतना स्मार्ट नहीं है (इसीलिए आपको उस विधि को चिह्नित करना होगा)। तकनीकी रूप से यह कॉल के लिए गहराई तक जा सकता है लेकिन यह आईएमओ के लायक नहीं है। इसके अलावा, क्या होगा यदि आपकी Init विधि virtual है और एक व्युत्पन्न प्रकार केवल S को प्रारंभ नहीं करता है? बहुत सारे परिदृश्य आईएमओ और संकलक को बताने के लिए विशेषताओं के साथ सजाना "मुझे पता है कि मैं क्या कर रहा हूं" बेहतर है।
 – 
Luke Vo
22 नवम्बर 2021, 17:57
@LukeVo: जब विधि को वर्चुअल के रूप में चिह्नित किया जाता है - तो यह संकलक चेतावनी को ट्रिगर करने का एक ठोस कारण होगा। जब विधि आभासी नहीं होती है, तो इसे ओवरराइड नहीं किया जा सकता है, इसलिए एस को प्रारंभ करने वाली विधि को कॉल किया जाना चाहिए। अन्यथा Init को ओवरराइड करने का प्रयास इसके बजाय कंपाइलर त्रुटि को ट्रिगर करेगा। विधि छिपाने के मामले में - मूल इनिट वैसे भी बुलाया जाएगा। लेकिन आपने मुझे उत्सुक बना दिया - क्या MemberNotNullAttribute का उपयोग करके किसी तरह कोड को तोड़ना संभव है? मुझे लगता है कि सीए प्रदर्शन कारण के लिए विशेषता मौजूद है, जैसा आपने उल्लेख किया है।
 – 
Harry
22 नवम्बर 2021, 18:37
मैंने इसे protected virtual void Init() में बदलने की कोशिश की और इसे व्युत्पन्न प्रकार से ओवरराइड किया। यदि आप base.Init() को कॉल नहीं करते हैं, तो आपको वही चेतावनी प्राप्त होती है। कंपाइलर गैर-वर्चुअल Init के बारे में, प्रदर्शन एक कारण IMO होगा, दूसरा है, Init आगे और तरीकों को कॉल कर सकता है InitS कॉल InternalInitS लाइन के नीचे और यह सिर्फ नहीं है इसके लायक।
 – 
Luke Vo
22 नवम्बर 2021, 18:45

1 उत्तर

सबसे बढ़िया उत्तर

MemberNotNullAttribute< का इस्तेमाल करें /a> अपने फ़ंक्शन को चिह्नित करने के लिए:

using System.Diagnostics.CodeAnalysis;

class Test
{

    string S { get; set; }

    public Test()
    {
        Init();
    }

    [MemberNotNull(nameof(S))]
    private void Init()
    {
        S = "hello";
    }

}

कंपाइलर अब शिकायत करेगा अगर आप Init में S को इनिशियलाइज़ नहीं करते हैं:

enter image description here

अधिक परिदृश्य देखें इस आलेख में: नल के लिए गुण- राज्य स्थैतिक विश्लेषण

6
Luke Vo 22 नवम्बर 2021, 17:43
यही वह है जिसकी तलाश में मैं हूं। वे सब कुछ सोचते थे। मुझे लगता है कि अगर यह स्वचालित होगा, तो यह सीए को काफी धीमा और शायद गलतियों के लिए भी कमजोर बना सकता है। शायद यह भी है: "यदि आप ऐसा संकेत देते हैं, तो कृपया इसे कोड में स्पष्ट रूप से और स्पष्ट रूप से नोट करें" कारण, यह भी काफी उचित है।
 – 
Harry
22 नवम्बर 2021, 18:39