2012-01-23 10 views
10

मैं इसविधि समाप्त होने के बाद भी थ्रेड स्थानीय चर का उपयोग कैसे कर सकता है?

public void MyMethod() 
    { 
     int i = 0; 

     var thread = new Thread(() => 
     { 
      Thread.Sleep(100); 

      if (i == 0) 
      { 
       Console.WriteLine("Value not changed and is {0}", i); 
      } 
      else 
      { 
       Console.WriteLine(" Value changed to {0}.", i); 
      } 
     }); 

     thread.Start(); 


     i = 1; 
    } 

यहाँ विधि की तरह एक सी # विधि है जो स्थानीय विधि में बनाया चर का उपयोग एक धागा बनाता है कहो। जब तक यह इस चर का उपयोग करता है तब तक विधि समाप्त हो जाती है और इस प्रकार एक स्थानीय चर मैं अस्तित्व में नहीं होना चाहिए। लेकिन कोड बिना किसी परेशानी के चलाता है। विधि समझने के बाद मेरी समझ के अनुसार स्थानीय चर मौजूद नहीं है। मैं इसे प्राप्त करने में सक्षम नहीं हूं।

उत्तर

4

मेरी समझ के अनुसार विधि ब्लॉक समाप्त होने के बाद स्थानीय चर मौजूद नहीं हैं। मैं इसे प्राप्त करने में सक्षम नहीं हूं।

आपकी समझ बस गलत है। स्थानीय चर की परिभाषा विशेषता यह है कि इसका नाम केवल अपने घोषित ब्लॉक के दायरे में है। यही कारण है कि इसे "स्थानीय" चर कहा जाता है - क्योंकि इसका नाम केवल स्थानीय रूप से दिखाई देता है।

आपको विश्वास है कि "स्थानीय" का मतलब है "छोटा रहता है"। यह गलत है; जब स्थानीय हो सकता है तो स्थानीय चर कम रहता है, लेकिन ऐसी तीन स्थितियां होती हैं जिनमें यह नहीं हो सकता है: जब यह किसी अज्ञात फ़ंक्शन के बंद-ओवर बाहरी चर होता है, जब यह एक इटरेटर ब्लॉक में होता है, या जब यह होता है एसिंक ब्लॉक।

संयोग से आपका प्रश्न पिछले सप्ताह मेरे ब्लॉग का विषय था; अधिक जानकारी के लिए यह देखें:

http://blogs.msdn.com/b/ericlippert/archive/2012/01/16/what-is-the-defining-characteristic-of-a-local-variable.aspx

+0

आईएल में उपयोग की जाने वाली इकाई के प्रकार का वर्णन करने के लिए आप किस शब्द का उपयोग कक्षा क्षेत्रों में नहीं उठाए गए चर को पकड़ने के लिए करते हैं? कुछ जो चर के रूप में लिखा गया है लेकिन एक कंपाइलर-क्लास में आयोजित किया गया है, एक निष्पादन दृष्टिकोण से, एक वर्ग क्षेत्र है। – supercat

+0

@supercat: मैं इसे एक स्थानीय चर कहूंगा। लेकिन मैं * एमएसआईएल * भाषा के बारे में बात करूँगा, सी # भाषा के बारे में नहीं। –

+0

जिज्ञासा से, क्या आप जानते हैं कि सी # को बनाने वाले लोगों को यह माना जाता है कि बंद होने में उपयोग किए जाने वाले चर को घोषित किया जा सकता है? मैं मानता हूं कि बंद हो सकते हैं, लेकिन बंद होने में चर के अंतर्निहित होस्टिंग खतरनाक लगते हैं और कभी-कभी अस्पष्ट अर्थशास्त्र उत्पन्न कर सकते हैं। स्पष्ट रूप से घोषणाओं को घोषित करने से अर्थशास्त्र स्पष्ट हो जाएगा। – supercat

4

इसे closure कहा जाता है।
यह विधि के जीवनकाल से परे स्थानीय चर फैलाता है।

15

यह काम करता है क्योंकि संकलक closure का उपयोग करने के लिए आपके कोड को फिर से लिखता है।

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

विवरण के लिए, यह blog post on closures देखें जो आपको संकलक के बारे में कोई अंदाज़ा देता है।

0

लैम्बडा अभिव्यक्ति जिसे आपने एक नए थ्रेड के रूप में लॉन्च किया है, मुझे closure बनाता है; चूंकि वेरिएबल पर बंद होने के करीब और मूल्य नहीं, थ्रेड बाहरी ऑब्जेक्ट के समान वस्तु को संदर्भित करता है और उस बाहरी दायरे को समाप्त होने के बाद भी इसके चर का उपयोग करने में सक्षम होगा।

0

एक सी # संकलक आम तौर पर एक मध्यवर्ती 'भाषा' MSIL कहा जाता है जो, जैसे सी #, स्थानीय चर है करने के लिए सी # कोड बदल देता है। एमएसआईएल में स्थानीय चर व्यवहार करते हैं क्योंकि आप सी # चर के व्यवहार की अपेक्षा करते हैं: जब वे नियमित रूप से परिभाषित होते हैं तो वे अस्तित्व में रहते हैं। इसके अलावा, जब स्थानीय चर का उपयोग करने वाले सी # कोड का अनुवाद एमएसआईएल कोड में किया जाता है जो स्थानीय चर का उपयोग करता है, तो उन सी # चर एमएसआईएल की तरह व्यवहार करते हैं: परिभाषित कार्य समाप्त होने पर वे अस्तित्व में रहते हैं। स्थानीय चर का उपयोग करने वाले सभी सी # कोड, हालांकि, उन्हें स्टोर करने के लिए एमएसआईएल स्थानीय चर का उपयोग नहीं करते हैं।

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

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

+0

@abelenky: क्षमा करें। – supercat

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