2012-05-09 14 views
5

लिंक क्वेरी में घोषित स्थानीय चर का दायरा क्या है।लिनक अज्ञात विधि (बंद) में स्थानीय चरणीय दायरा

मैं निम्नलिखित कोड

static void Evaluate() 
    { 
     var listNumbers = Enumerable.Range(1, 10).Select(i => i); 
     int i = 10; 
    } 

संकलक लाइन पूर्णांक मैं = 10 पर त्रुटि चिह्नित किये लिख रहा था,

A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else 

बताते हुए मुझे समझ में क्यों इस त्रुटि आ रहा है असमर्थ हूँ।

मेरी समझ यह थी कि i पहली पंक्ति (फोरैच लूप में) के बाद दायरे से बाहर हो जाएगा। तो i फिर से घोषित किया जा सकता है।

वास्तविक व्यवहार यह है कि i को पहली पंक्ति (फ़ोरैच लूप में) के बाद एक्सेस नहीं किया जा सकता है, जो सही है। लेकिन i को फिर से घोषित नहीं किया जा सकता है। यह अजीब लगता है।

EDIT यह एंड्रेस द्वारा प्रतिक्रिया के आधार पर एक निम्न प्रश्न है। जवाब बहुत अच्छा है, लेकिन आगे संदेह का कारण बनता है।

static void Evaluate3() 
    { 
     var listNumbers = Enumerable.Range(1, 10).Select(i => i); 
     var listNumbers1 = Enumerable.Range(1, 10).Select(i => i); 
    } 

समारोह के तर्क के आधार पर मूल्यांकन कि .Select (i => मैं), और int i = 10, दोनों मैं, ब्लॉक और इसलिए जटिलता त्रुटि कार्य करने के लिए स्थानीय कर रहे हैं।

फ़ंक्शन Evaluate3 को संकलित नहीं करना चाहिए साथ ही विधि ब्लॉक में दो हैं, लेकिन यह किसी भी चेतावनी/त्रुटि के बिना सफलतापूर्वक संकलित हो रहा है।

प्रश्न, या तो दोनों मूल्यांकन और मूल्यांकन 3 संकलित नहीं होना चाहिए, या दोनों को संकलित करना चाहिए।

+0

क्या आप वाकई linq कथन के साथ कोई समस्या है? यदि आप इसे 'select (x => x)' के रूप में दोबारा हटाते हैं तो क्या त्रुटि वास्तव में दूर जाती है? –

+0

यह समस्या LINQ से संबंधित नहीं है। यह linq के अंदर lamda अभिव्यक्ति से संबंधित है। । चयन करें (x => x) -> हाँ त्रुटि दूर हो जाती है – Tilak

+0

हम बड़े पैमाने पर linq का उपयोग करते हैं और मैं कभी भी ऐसा नहीं हुआ। कोशिश की और हाँ, मुझे एक ही शिकायत मिलती है। जो मैं वीडर मानता हूं वह यह है कि मेरे पास 'var listNumbers = संख्यात्मक। श्रेणी (1, 10) हो सकती है। चयन करें (i => i); var listNumbers2 = listNumbers.Cast ()। चयन करें (i => i); 'और यह एक त्रुटि को फेंक नहीं देता है, भले ही मैं एक ही परिवर्तनीय नाम का उपयोग कर रहा हूं, एक बार एक पूर्णांक के रूप में और एक बार एक स्ट्रिंग के रूप में। ऐसा लगता है कि 'i' के दूसरे उपयोग में भी त्रुटि होनी चाहिए ... –

उत्तर

7

यहाँ ध्यान दें करने के लिए महत्वपूर्ण तथ्य यह है कि एक घोषणा है। .NET में स्थानीय चर की घोषणा पूरे क्षेत्र के लिए उस नाम और स्थानीय को आरक्षित करने के लिए संकलक को सिर्फ एक निर्देश है। इसका अर्थ यह है कि इसे घोषित करने के बाद, से पहले और बाद में सभी लाइनों के लिए आरक्षित है।

वास्तव में, इसका मतलब है कि आप वास्तव में Evaluate के रूप में पढ़ा जाना चाहिए:

static void Evaluate() 
{ 
    int i; 
    var listNumbers = Enumerable.Range(1, 10).Select(i => i); 
    i = 10; 
} 

और अगर आप अपने विधि तदनुसार बारे में तो आप उस संकलक त्रुटि बजाय लैम्ब्डा घोषणा पर होता है देखेंगे - जो पूरी तरह से उचित है। शुक्र है, सी # कंपाइलर एक मानव परिप्रेक्ष्य से पर्याप्त चालाक है, यह पहचानने के लिए कि हमें पर कोड का ऑर्डर करना महत्वपूर्ण है, और यह वास्तव में संकलक त्रुटि को असाइन करता है जो भी स्रोत लाइन दूसरी या बाद की घोषणा है; इसलिए Evaluate के आपके संस्करण में यह int i = 10; लाइन पर होता है। फ़ंक्शन के स्थानीय i के वास्तविक जीवनकाल के इस ज्ञान के साथ, कंपाइलर सही है: का उपयोग लैम्ब्डा में i के पहले उपयोग के साथ संघर्ष करेगा।

आप स्पष्ट scoping का उपयोग इस से बचने के लिए कर सकते हैं:

static void Evaluate() 
{ 
    var listNumbers = Enumerable.Range(1, 10).Select(i => i); 
    { 
    int i = 10; 
    } 
} 

Evaluate3 के मामले तो आप बस ध्यान दें, जबकि दोनों lambdas माता पिता समारोह गुंजाइश साझा करते हैं, वे भी अपने स्वयं के है, और यह वहाँ में है कि उनके i एस घोषित किए गए हैं - और यही कारण है कि वे एक-दूसरे के साथ हस्तक्षेप नहीं करते हैं (वे वास्तव में, भाई के दायरे हैं)। एक ही समारोह के भीतर जो है, अलग-अलग दायरों में, -

static void Evaluate() 
{ 
    { 
    int i; 
    } 
    int i; //<-- error 
} 

static void Evaluate3() 
{ 
    { 
    int i; 
    } 
    { 
    int i; 
    } 
    //fine here - both i's are in different scopes. 
} 

और यह वास्तव में दूसरे परिदृश्य है कि मैं पहले के लिए स्पष्ट scoping का उपयोग किया है यहाँ:

संयोग Evaluate और Evaluate3 अंततः इस के लिए सरल किया जा सकता है जहां i वास्तव में प्रत्येक में एक अलग प्रकार है। जैसे मैं कहता हूं - मैंने इसे फिर से नहीं किया है और प्रश्न में कोड अब लाइव नहीं है :)

+0

यदि आप कोडिंग त्रुटि बिंदु कोडिंग से देखते हैं, तो मैं इसे फिर कभी नहीं करूँगा। यह सिर्फ मुझे सामना करना पड़ा है, और इस पर दिमाग खाली था। – Tilak

+0

उत्तर के लिए धन्यवाद, मैंने प्रतिक्रिया के आधार पर एक फॉलो अप प्रश्न रखा है। – Tilak

+0

मुझे व्यवहार और स्पष्टीकरण समझा गया है। मेरा लेना यह है कि यह पैरेंट विधि ब्लॉक का दायरा नहीं है (पहले कोड में मूल्यांकन करें, दूसरे कोड पर मूल्यांकन 3) जो इस मुद्दे का कारण बन रहा है। यह बेनामी विधि के अंदर का दायरा है जो इस मुद्दे का कारण बन रहा है। चूंकि अज्ञात विधि बाहरी फ़ंक्शन के स्थानीय चरों तक पहुंच सकती है, मूल्यांकन में, यह त्रुटि उत्पन्न कर रहा है क्योंकि यह दो i देख रहा है। Evaluate3 में, चूंकि कोई lamda अभिव्यक्ति दो देख रहा है, कोई चेतावनी/त्रुटि ध्वजांकित नहीं है। मैं आपकी राय सुनना चाहता हूं। यदि आप सहमत हैं, तो बेहतर शब्द के साथ उत्तर अपडेट करें। मैं उतना अभिव्यक्तिपूर्ण नहीं हूं जितना आप हैं। – Tilak

1
the spec से

:

The scope of a local variable declared in a local-variable-declaration is the block in which the declaration occurs. It is an error to refer to a local variable in a textual position that precedes the local-variable-declarator of the local variable. 

आपका लैम्ब्डा i => i स्थानीय चर int i = 10 के दायरे भले ही यह पहले से घोषित किया जाता है के अंदर है। एक त्रुटि फेंकने की बजाय, आप घोषित होने से पहले i का उपयोग कर रहे हैं, संकलक मददगार रूप से यह इंगित कर रहा है कि आपने पहले से ही i का उपयोग कुछ और करने के लिए किया है और यह घोषणा उसमें बदल जाएगी।

संपादित करें: अगर आपके अपडेट के बाद:

पहले मामले में, अपने पहले i लैम्ब्डा के भीतर संलग्न है, लेकिन अपने दूसरे i लैम्ब्डा सहित पूरे Evaluate विधि शामिल हैं - इसलिए आप त्रुटि मिलती है।

दूसरे मामले में, अपने पहले i अपने लैम्ब्डा के भीतर संलग्न है, और अपने दूसरे i भीतर अपने लैम्ब्डा संलग्न है - न i अन्य के दायरे के भीतर है, इसलिए वहाँ कोई त्रुटि है।

आपका पैराग्राफ "तर्क के आधार पर ... मैं दोनों, ब्लॉक ब्लॉक करने के लिए स्थानीय हैं ..." गलत है - पहले i फ़ंक्शन ब्लॉक के लिए स्थानीय नहीं है लेकिन लैम्ब्डा में है।- बस नहीं बिंदु है जिस पर यह घोषित किया जाता है से

int i; 

... पूरे संलग्न गुंजाइश भर में प्रभाव शुरू से ही लेता है खत्म करने के लिए:

+0

यद्यपि अजीब व्यवहार की तरह लगता है। पहले 'i' का उपयोग केवल 'चयन' कथन के अंदर किया जा रहा है, इसलिए आसान धारणा यह होगी कि यह केवल 'चयन करें' कथन के लिए स्थानीय है, न कि संपूर्ण 'मूल्यांकन()' विधि। –

+0

@ ग्रांट पहला 'i' वास्तव में' चयन 'कथन के लिए स्थानीय है "। हालांकि, दूसरा 'i' लैम्ब्डा समेत संपूर्ण 'मूल्यांकन()' विधि के लिए स्थानीय है। – Rawling

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