दिलचस्प पोस्ट
कक्षा और मॉड्यूल के बीच अंतर कैसे एक बिटमैप करने के लिए एक Drawable कन्वर्ट करने के लिए? जावास्क्रिप्ट में यूआरएल के होस्टनाम भाग को कैसे निकालें XPath को बाल नोड मूल्यों को क्वालीफाइंग करने के लिए स्ट्रिंग कन्वर्टनेशन वापस करना गलतर INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL के लिए Mojarra JSF 2.1 में काम करें एंड्रॉइड स्टूडियो लॉकैट शो में कुछ भी नहीं है ग्रैडल डीएसएल विधि नहीं मिली: 'रनप्रागार्ड' स्मृति में वस्तु का आकार कैसे प्राप्त करें? PHP द्वारा वेबपेज के ओपन ग्राफ़ प्रोटोकॉल कैसे प्राप्त करें? अजगर: सूचियों की एक सूची से डुप्लिकेट को निकालना डायनेमिक का उपयोग करके ऑब्जेक्ट को XML के लिए डीसरियल बनाना जावा गेम लूप (पेंटिंग) मेरी खिड़की को जमा देता है डीबगिंग "एलीमेंट बिंदु पर क्लिक करने योग्य" त्रुटि नहीं है जावास्क्रिप्ट के साथ ब्राउज़र सीएसएस संपत्ति समर्थन की जाँच करें? जावा में अपवाद क्यों पकड़ते हैं, जब आप थ्रोबैबल्स को पकड़ सकते हैं?

लम्बा लूप में चर कैप्चर – यहाँ क्या होता है?

मैं अपने सिर के आसपास की कोशिश कर रहा हूँ, यहाँ क्या होता है? कम्पाइलर का किस तरह का कोड है?

public static void vc() { var listActions = new List<Action>(); foreach (int i in Enumerable.Range(1, 10)) { listActions.Add(() => Console.WriteLine(i)); } foreach (Action action in listActions) { action(); } } static void Main(string[] args) { vc(); } 

आउटपुट: 10 10 .. 10

इसके अनुसार, एक्शन हेल्पर का एक नया उदाहरण प्रत्येक पुनरावृत्त के लिए बनाया जाएगा। तो उस मामले में, मुझे लगता होगा कि यह प्रिंट 1..10 होगा। क्या कोई मुझे कंपाइलर यहाँ क्या कर रहा है की कुछ छद्म कोड दे सकता है?

धन्यवाद।

वेब के समाधान से एकत्रित समाधान "लम्बा लूप में चर कैप्चर – यहाँ क्या होता है?"

इस लाइन में

  listActions.Add(() => Console.WriteLine(i)); 

चर i , कब्जा कर लिया है, या यदि आप चाहें, तो उस चर के स्मृति स्थान पर एक सूचक बनाया। इसका अर्थ है कि प्रत्येक प्रतिनिधि को उस मेमोरी स्थान पर एक सूचक मिला है। इस लूप निष्पादन के बाद:

 foreach (int i in Enumerable.Range(1, 10)) { listActions.Add(() => Console.WriteLine(i)); } 

स्पष्ट कारणों के लिए i 10 , इसलिए मेमोरी सामग्री जो कि Action (एस) में मौजूद सभी बिंदुओं की ओर इशारा करते हैं, 10 हो जाती हैं।

दूसरे शब्दों में, i कब्जा कर लिया है।

वैसे, ध्यान दें, कि एरिक लिपर्ट के अनुसार, यह "अजीब" व्यवहार C# 5.0 में हल किया जाएगा।

तो C# 5.0 आपका प्रोग्राम अपेक्षित रूप से प्रिंट करेगा:

 1,2,3,4,5...10 

संपादित करें:

विषय पर एरिक लिपर्ट की पोस्ट नहीं मिल सकती, लेकिन यहां एक और है:

लूप में बंद होने पर रिजिट किया गया

कम्पाइलर का किस तरह का कोड है?

ऐसा लगता है जैसे आप यह उम्मीद करते हैं:

 foreach (int temp in Enumerable.Range(1, 10)) { int i = temp; listActions.Add(() => Console.WriteLine(i)); } 

यह प्रत्येक पुनरावृत्ति के लिए एक अलग varaible का उपयोग करता है, और इसलिए लैम्ब्डा बनाए जाने के समय चर के मूल्य पर कब्जा कर लिया जाएगा। असल में, आप इस सटीक कोड का इस्तेमाल कर सकते हैं और परिणाम आप चाहते हैं।

लेकिन वास्तव में संकलक वास्तव में क्या करता है:

 int i; foreach (i in Enumerable.Range(1, 10)) { listActions.Add(() => Console.WriteLine(i)); } 

इससे यह साफ हो जाता है कि आप प्रत्येक चलना पर एक ही चर पर कब्जा कर रहे हैं। जब आप बाद में जाते हैं और वास्तव में उस कोड को निष्पादित करते हैं, तो वे सभी उसी मूल्य का उल्लेख करते हैं जो पहले से 10 तक बढ़ा है।

यह संकलक या रनटाइम में एक बग नहीं है … यह भाषा डिजाइन टीम के एक सचेत निर्णय था। हालांकि, यह कैसे काम करता है, इस बारे में भ्रम के कारण, उन्होंने इस निर्णय को उलट कर दिया है और सी # 5 के लिए उम्मीद की तरह काम करने के लिए इसे तोड़ने के बदलाव के जोखिम का फैसला किया है ।

संक्षेप में क्या हो रहा है कि संकलक आपके int i को लूप के बाहर घोषित कर रहा है और इस प्रकार हर एक्शन के लिए इसका नया मान नहीं बना रहा है, केवल हर बार उसी को संदर्भित करता है जब तक आप कोड को निष्पादित कर लेते हैं I 10 है और इसलिए यह बहुत कम 10 प्रिंट करता है।