दिलचस्प पोस्ट
एक <select> तत्व के लटकती तीर को छिपाने के लिए सही "-मोझ-उपस्थित" मान क्या है डेटाबेस में बुलेट्स को सॉर्ट करें वेब संदर्भ और सेवा संदर्भ में अंतर? रिलेशनल डेटाबेस में एक कैटलॉग और एक स्कीमा के बीच क्या अंतर है? जीडीबी के साथ मानक कंटेनर (एसटीडी :: नक्शा) का निरीक्षण करना MySQL में दो डेटासेट के बीच अंतर की गणना करें स्कैनर अंतरिक्ष के बाद नहीं देखता है JSF / प्राइमफेस AJAX अपडेट्स टूटता है jQuery इवेंट श्रोता फ़ंक्शन बाइंडिंग वर्णक्रम क्रम में सरंटा क्रमबद्ध करना (केस असंवेदनशील) पीडीओ बाँध पाराम बनाम Matlab में एक फ़ोल्डर में फ़ाइलों के माध्यम से लूप क्या $ (दस्तावेज़) .ready () भी सीएसएस तैयार है? एक MongoDB डेटाबेस में छवियों को स्टोर करें Info.plist अपलोड त्रुटि में CFBundleVersion एक PostgreSQL फ़ंक्शन पैरामीटर के रूप में तालिका का नाम

सी # के एक foreach में चर के पुन: उपयोग के लिए एक कारण है?

जब सी # में लैम्ब्डा अभिव्यक्ति या अनाम तरीकों का उपयोग कर रहे हैं, तो हमें संशोधित बंद होने वाले फाफ़ल तक पहुंच से सावधान रहना होगा। उदाहरण के लिए:

foreach (var s in strings) { query = query.Where(i => i.Prop == s); // access to modified closure ... } 

संशोधित समापन के कारण, उपरोक्त कोड क्वेरी के सभी Where कारण s के अंतिम मूल्य पर आधारित होगा।

जैसा कि यहां समझाया गया है , ऐसा इसलिए होता है क्योंकि उपर्युक्त पाश में घोषित चर चर को कंपाइलर में अनुवादित किया गया है:

 string s; while (enumerator.MoveNext()) { s = enumerator.Current; ... } 

इस तरह के बजाय:

 while (enumerator.MoveNext()) { string s; s = enumerator.Current; ... } 

जैसा कि यहाँ बताया गया है , पाश के बाहर एक चर को घोषित करने के लिए कोई प्रदर्शन फायदे नहीं हैं, और सामान्य परिस्थितियों में एकमात्र कारण यह है कि मैं ऐसा करने के बारे में सोच सकता है यदि आप चर का उपयोग करने के लिए लूप के दायरे से बाहर की योजना बनाते हैं:

 string s; while (enumerator.MoveNext()) { s = enumerator.Current; ... } var finalString = s; 

हालांकि foreach लूप में परिभाषित चर को लूप के बाहर नहीं इस्तेमाल किया जा सकता है:

 foreach(string s in strings) { } var finalString = s; // won't work: you're outside the scope. 

इसलिए कंपाइलर वेरिएबल को ऐसे तरीके से घोषित करता है जिससे किसी त्रुटि के लिए यह अत्यधिक प्रवण होता है जो कि कभी-कभी मुश्किल नहीं मिल पाता है और डीबग करता है, जबकि कोई ज्ञात फायदे नहीं बनाते हैं

क्या ऐसा कुछ है जो आप foreach loops के साथ ऐसा कर सकते हैं कि यदि आप इन्हें आंतरिक-स्कॉक्स्ड वेरिएबल के साथ संकलित नहीं किया जा सकता है, या यह केवल एक मनमाना पसंद है जो गुमनाम विधियों और लैम्ब्डा भावों से पहले बनाया गया था या उपलब्ध है, और जो तब से संशोधित नहीं किया गया है?

वेब के समाधान से एकत्रित समाधान "सी # के एक foreach में चर के पुन: उपयोग के लिए एक कारण है?"

कंपाइलर वैरिएबल को ऐसे तरीके से घोषित करता है जिससे यह किसी त्रुटि की संभावना पैदा कर सकता है जो कि कभी-कभी मुश्किल नहीं मिल पाता है और डीबग करता है, जबकि कोई लाभदायक लाभ नहीं पैदा करता है।

आपकी आलोचना पूरी तरह से उचित है।

मैं इस समस्या पर यहां विस्तार से चर्चा करता हूं:

पाश चर पर समापन हानिकारक माना जाता है

क्या ऐसा कुछ है जो आप foreach loops के साथ ऐसा कर सकते हैं कि यदि वे आंतरिक-स्कॉक्स्ड वेरिएबल के साथ संकलित नहीं किए गए हैं? या यह सिर्फ एक मनमाना पसंद है, जो गुमनाम तरीके और लैम्ब्डा अभिव्यक्ति से पहले उपलब्ध था या सामान्य था, और तब से संशोधित नहीं किया गया है?

बाद वाला। सी # 1.0 विनिर्देश वास्तव में यह नहीं कहता कि क्या लूप वैरिएबल लूप बॉडी के अंदर या बाहर था, क्योंकि इसमें कोई अंतर नहीं आया। जब सी # 2.0 में क्लोजर सिमेंटिक्स पेश किए गए थे, तो लूप वैरिएबल को "लुक" के साथ संगत करने के लिए विकल्प बनाया गया था।

मुझे लगता है कि यह कहना उचित है कि सभी निर्णयों पर खेद है। यह सी # में सबसे खराब "गेतकस" में से एक है, और हम इसे ठीक करने के लिए तोड़फोड़ में बदलाव करने जा रहे हैं। सी # 5 में फोरश लूप वैरिएबल तार्किक रूप से लूप के शरीर के अंदर होगा, और इसलिए बंद होने पर हर बार एक ताजा कॉपी मिल जाएगी।

लूप के for परिवर्तित नहीं किया जाएगा, और परिवर्तन C # के पिछले संस्करणों के लिए "वापस पोर्ट किया जाएगा" नहीं होगा। इस मुहावरे का इस्तेमाल करते समय आपको सावधान रहना चाहिए

आप जो पूछ रहे हैं वह एरिक लिपरटे द्वारा अपने ब्लॉग पोस्ट में पूरी तरह से कवर किया गया है, लूप वैरिएबल को खत्म करना हानिकारक माना जाता है और इसकी अगली कड़ी

मेरे लिए, सबसे तर्कसंगत तर्क यह है कि प्रत्येक चलना में नया चर होने के for(;;) शैली लूप के for(;;) असंगत होगा। क्या आप for (int i = 0; i < 10; i++) प्रत्येक पुनरावृत्ति में एक नया int i होने की अपेक्षा करेंगे?

इस व्यवहार के साथ सबसे आम समस्या पुनरावृत्ति चर पर समापन कर रही है और इसका एक आसान समाधान है:

 foreach (var s in strings) { var s_for_closure = s; query = query.Where(i => i.Prop == s_for_closure); // access to modified closure 

इस मुद्दे के बारे में मेरा ब्लॉग पोस्ट: C # पर अग्रविकल्प चर पर क्लोजर

इसके द्वारा काट लिया गया है, मुझे अंदरूनी परिभाषा वाले चर को शामिल करने की आदत है जो मैं किसी भी बंद करने के लिए उपयोग कर रहा हूं। आपके उदाहरण में:

 foreach (var s in strings) { query = query.Where(i => i.Prop == s); // access to modified closure 

मैं करता हूँ:

 foreach (var s in strings) { string search = s; query = query.Where(i => i.Prop == search); // New definition ensures unique per iteration. 

एक बार आपके पास यह आदत है, तो आप इसे बहुत दुर्लभ मामले में से बच सकते हैं, जो आप वास्तव में बाहरी स्कोप से बाँधना चाहते थे। ईमानदारी से, मुझे नहीं लगता कि मैंने कभी ऐसा किया है।

सी # 5.0 में, यह समस्या ठीक हो गई है और आप पाश चर पर बंद कर सकते हैं और आपके द्वारा अपेक्षित परिणाम प्राप्त कर सकते हैं।

भाषा विनिर्देश कहते हैं:

8.8.4 उपर्युक्त बयान

(…)

प्रपत्र का एक उपन्यास बयान

 foreach (V v in x) embedded-statement 

इसके बाद इसका विस्तार किया जाता है:

 { E e = ((C)(x)).GetEnumerator(); try { while (e.MoveNext()) { V v = (V)(T)e.Current; embedded-statement } } finally { … // Dispose e } } 

(…)

जबकि लूप के अंदर v का स्थान महत्वपूर्ण है, यह कैसे एम्बेडेड-स्टेटमेंट में आने वाले किसी भी अज्ञात कार्य के द्वारा कैप्चर किया जाता है। उदाहरण के लिए:

 int[] values = { 7, 9, 13 }; Action f = null; foreach (var value in values) { if (f == null) f = () => Console.WriteLine("First value: " + value); } f(); 

यदि v को लूप के बाहर घोषित किया गया था, तो इसे सभी पुनरावृत्तियों के बीच साझा किया जाएगा, और लूप के बाद इसका मूल्य अंतिम मूल्य होगा, 13 , जो कि f के अभिवादन को प्रिंट होगा। इसके बजाय, क्योंकि प्रत्येक पुनरावृत्ति का अपना चर वाला v , पहली बार चलने वाले f में से एक को कब्जा कर लिया गया एक वाला मान 7 को जारी रखेगा, जो कि मुद्रित किया जाएगा। ( ध्यान दें: जबकि सी # के पहले के संस्करणों में लूप के बाहर घोषित v )