2012-02-17 14 views
6

सी # परिवर्तनीय स्कॉइंग की बात करते समय काफी नाइट-पिकिंग है। यह कैसे संभव है कि यह इस कोड को स्वीकार करता है:सी # परिवर्तनीय scoping संगत नहीं है?

class Program 
{ 
    int x = 0; 

    void foo() 
    { 
     int x = 0; 
     x = 1; 

     Console.WriteLine(x); 
    } 
} 

यदि आप मुझसे पूछें, तो यह एक स्पष्ट नामकरण संघर्ष है। अभी भी संकलक (वीएस 2010) इसे स्वीकार करता है। क्यूं कर?

+4

आप 'x' और' this.x' का उल्लेख कर सकते हैं, इसलिए कोई समस्या नहीं है। – Blorgbeard

+0

असल में यह संगत है। यदि आपके पास शून्य foo() फ़ंक्शन में x = 0 था तो यह एक्स से वैरिएबल उठाएगा जिसे आपने पहले परिभाषित किया था। क्योंकि आपके पास int x = 0 है जिस विधि में आपके इरादे के लिए एक नया वैरिएबल तत्काल है। लेकिन यदि आप foo विधि के बाहर x के मान को देखते हैं तो यह अभी भी 0 होगा क्योंकि आप एक अलग दायरे में हैं। – Brian

+0

यदि आप क्लास सदस्य के समान नाम के साथ स्थानीय वैरिएबल प्राप्त करने में सक्षम नहीं होना चाहते हैं, तो आप रीशेपर प्राप्त कर सकते हैं और [इसे आपको ऐसा करने से रोक सकते हैं] (http://confluence.jetbrains.net/display/ReSharper/लोकल + चर + खाल + सदस्य)। – AakashM

उत्तर

12

यह नामकरण विरोधी नहीं है: सी # में, स्थानीय चर समान नाम के साथ आवृत्ति चर पर प्राथमिकता लेते हैं, क्योंकि उनके scope संकुचित हैं।

संकलक एक नाम घोषणा करने के लिए एक नाम संदर्भ मेल खाता है, यह इस विषय पर विस्तृत जानकारी के लिए सबसे संकीर्ण दायरे Reference Matching पर

दस्तावेज़ देखें के साथ मिलान घोषणा उपयोग करता है।

0

कोई नामकरण संघर्ष नहीं है। कंपाइलर हमेशा nearest/कम से कम स्कोप चर लेता है।

इस मामले में, एक्स चर आप foo में घोषित thats। प्रत्येक चर को एक विशिष्ट तरीके से एक्सेस किया जा सकता है, इसलिए कोई नामकरण संघर्ष नहीं है।

आप बाहरी एक्स पर पहुंचना चाहते हैं आप this.x उपयोग कर सकते हैं।

0

क्योंकि नियम है कि एक संघर्ष एक स्थानीय चर और एक वर्ग के सदस्य के बीच मौजूद हैं, स्थानीय चर उच्च पूर्वता है।

0

यह संदिग्ध नहीं है कि स्थानीय वैरिएबल होगा जो आपके फ़ंक्शन में दोबारा माना जाता है। यदि आपको क्लास वेरिएबल प्राप्त करने की आवश्यकता है तो यह .x नाम रिज़ॉल्यूशन की अनुमति देता है।

3

सामान्य है।

रचनाकारों में मैं अक्सर इसका उपयोग करता हूं।

public Person(string name) { 
    this.name = name; 
} 

अन्यथा सदस्य चर के नाम वाले विधि पैरामीटर घोषित करना संभव नहीं होगा।

18

सी # नाम छिपाने के नियम काफी जटिल हैं। भाषा आपके द्वारा उल्लेख किए जाने वाले मामले की अनुमति देती है, लेकिन कई समान मामलों को अस्वीकार करती है। इस जटिल विषय पर कुछ जानकारी के लिए

http://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/

देखें।

अपने विशिष्ट प्रश्न को संबोधित करने के लिए: संकलक निश्चित रूप से उस संघर्ष का पता लगा सकता है।

class P 
{ 
    int x; 
    void M() 
    { 
     x = 123; // The author intends "this.x = 123;" 
     int x = 0; 
    } 
} 

बराबर सी ++ प्रोग्राम कानूनी सी होगा ++, क्योंकि C++ एक स्थानीय चर इसकी घोषणा के बिंदु पर गुंजाइश में आता है: वास्तव में, यह कि संघर्ष पहचानता है। सी # में, एक स्थानीय चर अपने पूरे ब्लॉक में दायरे में है, और इसकी घोषणा से पहले इसका उपयोग अवैध है। आप इस कार्यक्रम के संकलन का प्रयास करें आपको मिलेगा:

error CS0844: Cannot use local variable 'x' before it is declared. 
The declaration of the local variable hides the field 'P.x'. 

देखें: स्थानीय घोषणा क्षेत्र छुपाता है।संकलक इसे जानता है। तो क्यों आपके मामले में यह एक क्षेत्र छिपाने के लिए त्रुटि नहीं है?

मान लीजिए कि तर्क के लिए यह एक त्रुटि होनी चाहिए। क्या यह भी एक त्रुटि होनी चाहिए?

class B 
{ 
    protected int x; 
} 
class D : B 
{ 
    void M() 
    { 
     int x; 
    } 
} 

क्षेत्र एक्स बी से डी के एक सदस्य विरासत के माध्यम से तो यह भी एक त्रुटि, सही होना चाहिए?

अब मान लीजिए कि आप इस कार्यक्रम फू निगम द्वारा निर्मित है:

class B 
{ 
} 

और इस कार्यक्रम बार निगम द्वारा उत्पादित:

class D : B 
{ 
    void M() 
    { 
     int x; 
    } 
} 

संकलित है। अब मान लीजिए कि फू कॉर्प उनके आधार वर्ग और जहाजों एक नया संस्करण अद्यतन करता है आप के लिए बाहर:

class B 
{ 
    protected int x; 
} 

तुम मुझे कि हर व्युत्पन्न वर्ग है कि अब संकलित करने के लिए असफल हो जाना चाहिए एक स्थानीय x नामित चर शामिल कह रहे हैं?

यह डरावना होगा। हमें स्थानीय चर को छाया सदस्यों को अनुमति देना है।

और यदि हम स्थानीय वर्गों को आधार वर्गों के सदस्यों को छायांकित करने की अनुमति देने जा रहे हैं, तो यह स्थानीय लोगों को कक्षाओं के सदस्यों को छाया देने की इजाजत नहीं देता है।

+0

यही मुझे भ्रमित कर रहा है। चूंकि सी # कई नामकरण विवादों को अस्वीकार करता है जो सी/सी ++ अनुमति देते हैं, मैं उपरोक्त परिदृश्य के लिए भी इस कठोरता की अपेक्षा करता हूं। – l33t

+1

@NOPslider: मैंने कुछ पाठ समझाया है कि यह एक बुरा विचार क्यों होगा। –

1

सी # 4.0 कल्पना का कहना है इस बारे में गुंजाइश घोंसले के माध्यम से छिपा:

3.7.1.1 के माध्यम से नेस्टिंग

नाम घोंसले के माध्यम से छुपा छिपाई जा रही है नामस्थान भीतर घोंसले नामस्थान या प्रकार की एक परिणाम के रूप में हो सकता है , कक्षाओं या structs के भीतर घोंसले प्रकार के परिणाम के रूप में, और पैरामीटर और स्थानीय परिवर्तनीय घोषणाओं के परिणामस्वरूप। उदाहरण

class A { 
    int i = 0; 
    void F() { 
     int i = 1; 
    } 
    void G() { 
     i = 1; 
    } 
} 
एफ विधि के भीतर

में, उदाहरण के चर मैं स्थानीय चर मैं द्वारा छिपा है, लेकिन जी विधि के भीतर, मैं अभी भी उदाहरण चर को दर्शाता है।

जब एक आंतरिक दायरे में कोई नाम बाहरी दायरे में एक नाम छुपाता है, तो वह उस नाम की सभी ओवरलोडेड घटनाओं को छुपाता है।

उदाहरण

class Outer { 
    static void F(int i) {} 
    static void F(string s) {} 
    class Inner 
    { 
     void G() { 
      F(1);   // Invokes Outer.Inner.F 
      F("Hello");  // Error 
     } 
     static void F(long l) {} 
    } 
} 

कॉल एफ (1) का आह्वान एफ इनर में घोषित क्योंकि एफ के सभी बाहरी घटनाओं भीतरी घोषणा से छिपे हुए हैं में

। उसी कारण के लिए, कॉल F ("हैलो") परिणाम संकलित-समय त्रुटि में होता है।

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