2017-05-15 9 views
23

मैं है निम्नलिखित कोड वर्ग:क्यों यह `सी # 6.0 ऑटो-प्रॉपर्टी प्रारंभ में उपलब्ध नहीं है?

Keyword 'this' is not available in the current context

मैं बस ऑटो-संपदा प्रारंभकर्ता का उपयोग नहीं करके इसे ठीक कर सकते हैं और स्पष्ट रूप से यह एक में ले जाते हैं:

public class Foo 
{ 
    public Nested Bar { get; } = new Nested(this); 

    public class Nested 
    { 
     public Nested(Foo foo) 
     { 
      foo.DoSomething(); 
     } 
    } 

    private void DoSomething() 
    { 

    } 
} 

हालांकि, मैं इस संकलन त्रुटि मिलती है इसके बजाय निर्माता:

public Nested Bar { get; } 

public Foo() 
{ 
    this.Bar = new Nested(this); 
} 

ऐसा क्यों है? क्या ऑटो-प्रॉपर्टी इनिशिलाइज़र वास्तव में आईएल में कन्स्ट्रक्टर कोड में अनुवादित नहीं है?

+3

क्योंकि ऑटो-प्रॉपर्टी प्रारंभकर्ता को प्रारंभिक के साथ बैकिंग फ़ील्ड में अनुवादित किया जाता है। आप फ़ील्ड प्रारंभकर्ता में इसका संदर्भ नहीं दे सकते क्योंकि फ़ील्ड प्रारंभकर्ता कन्स्ट्रक्टर से पहले चलता है, इसलिए उपयोग करने के लिए अभी तक कोई निर्मित ऑब्जेक्ट नहीं है। – Evk

+0

@Evk ऐसा नहीं है कि जब कन्स्ट्रक्टर चलता है तो ऑब्जेक्ट भी "अभी तक निर्मित नहीं है"? –

+0

एक दिलचस्प सवाल रोलैंड पिहलाकस! इस ऑब्जेक्ट को एक्सेस करने के लिए तैयार स्मृति के संदर्भ में पहले से मौजूद होना चाहिए। अन्यथा संपत्ति वहां नहीं होगी। लेकिन कुछ और शुरू नहीं हुआ है। कोई भी कन्स्ट्रक्टर में इनिट चरणों का गलत आदेश भी कर सकता है लेकिन प्रोग्रामर के लिए और अधिक स्पष्ट होगा। – Droidum

उत्तर

42

बस: आप प्रारंभकर्ताओं में this का उपयोग नहीं कर सकते हैं। विचार है कि एक अपूर्ण ऑब्जेक्ट से बचने से रोकने के लिए - Nested(this)कुछ भी आपके ऑब्जेक्ट पर कर सकता है, जिससे बहुत भ्रमित और बग को समझना मुश्किल हो जाता है। ध्यान रखें कि प्रारंभकर्ता से पहले आपके द्वारा जोड़े गए किसी भी निर्माता को निष्पादित करते हैं। एक ही बात क्षेत्र initializers के लिए भी विफल रहता है, बिल्कुल उसी तरह:

private Nested _field = new Nested(this); 

अनिवार्य रूप से, initializers सरल initializations प्रदर्शन करने का इरादा कर रहे हैं - 98% से समस्या का समाधान। this से जुड़ी कुछ भी जटिल है, और आपको अपना खुद का कन्स्ट्रक्टर लिखना होगा - और किसी भी समय के मुद्दों के लिए दोष लेना होगा :)

+0

टीआईएल! यदि आप कोई फर्क नहीं पड़ता है तो मैं थोड़ा उत्सुक हूं: क्या प्रारंभकर्ता में क्या हो सकता है इसके बारे में विवरण/दस्तावेज़ीकरण है? वे इसे बजाय कन्स्ट्रक्टर में क्यों नहीं डालते (स्पष्ट कन्स्ट्रक्टर कोड से पहले)? –

+4

@DatVM जो अनिवार्य रूप से आईएल स्तर पर * होता है; मैंने बहुत जानबूझकर कहा "कोई भी कन्स्ट्रक्टर जो आप जोड़ते हैं" - तो: * यदि आप * एक कन्स्ट्रक्टर जोड़ते हैं, तो इसमें अभी तक कुछ भी करने का समय नहीं होगा। प्रारंभिक आदेश के प्रश्न भी हैं: प्रारंभिककर्ता अभी तक क्यों चल रहे हैं? यदि आपके पास कन्स्ट्रक्टर का स्पष्ट समय नहीं है तो यह सही होने के लिए * बहुत मुश्किल हो जाता है। भाषा लेखकों को उन चीजों को पसंद नहीं है जो सूक्ष्म जटिलताओं को जोड़ते हैं, इसलिए: इस उपयोग को कन्स्ट्रक्टर –

+1

@datvm का उपयोग करने के लिए मजबूर होना पड़ता है प्री-कन्स्ट्रक्टर में इसे करने से 'निजी int a = this.b; निजी int b = this.a; '- जबकि विशेष रूप से असुरक्षित मामलों को शायद पकड़ा जा सकता है, उस संदर्भ थोक में 'इस' के उपयोग को रोकने के लिए यह बहुत आसान है। – IllusiveBrian

17

Why is it so? Isn't Auto-Property Initializer actually translated into constructor code in IL?

स्वचालित रूप से लागू संपत्ति प्रारंभकर्ताओं के नियम उसी कारण से फील्ड प्रारंभकर्ताओं के लिए समान हैं। ध्यान दें कि संपत्ति प्रारंभकर्ताओं को बेस क्लास निकायों से पहले निष्पादित किया जाता है, जैसे फील्ड प्रारंभकर्ता - ताकि आप अभी भी "कुछ हद तक अनियमित" ऑब्जेक्ट के संदर्भ में हैं; एक निर्माता शरीर के दौरान से भी ज्यादा।

तो आप कल्पना करना चाहिए कि संपत्ति इस में परिवर्तित किया जा रहा है:

private readonly Nested bar = new Nested(this); // Invalid 

public Nested Bar 
{ 
    get { return bar; } 
} 

संक्षेप में, इस प्रतिबंध को अपने आप को मुसीबत में हो रहा से आप को रोकने के लिए है। यदि आपको किसी संपत्ति को प्रारंभ करते समय this का संदर्भ लेना है, तो अपने दूसरे उदाहरण के अनुसार, इसे मैन्युअल रूप से कन्स्ट्रक्टर में करें। (यह मेरे अनुभव में अपेक्षाकृत दुर्लभ है।)

+0

क्या इसे 'readonly' फ़ील्ड में परिवर्तित नहीं किया जा रहा है? त्रुटि आपके दिमाग में क्यों होती है इसके लिए पूरी तरह से महत्वपूर्ण नहीं है। – TheLethalCoder

+0

@TheLethalCoder: हाँ, इसके लिए संपादित करेंगे। –

संबंधित मुद्दे