2013-02-27 31 views
35

1 बयान:ये linq आउटपुट अलग क्यों हैं?

IEnumerable<char> query = "Not what you might expect"; 

query = query.Where (c => c != 'a'); 
query = query.Where (c => c != 'e'); 
query = query.Where (c => c != 'i'); 
query = query.Where (c => c != 'o'); 
query = query.Where (c => c != 'u'); 

String.Join("", query) के आउटपुट: "Nt wht y mght xpct"

2 बयान:

query = "Not what you might expect"; 

foreach (char vowel in "aeiou") 
    query = query.Where (c => c != vowel); 

String.Join("", query) के आउटपुट: "Not what yo might expect"

इन बयानों से आउटपुट अलग हैं। क्या कोई भी समझा सकता है क्यों?

लैम्ब्डा अपने प्रश्न में पाश चर vowel कब्जा:

+4

आपको प्राप्त होने वाला आउटपुट क्या है? – Default

+1

इसका परिणाम इस बात पर निर्भर करेगा कि आप जिस .NET को लक्षित कर रहे हैं उसका संस्करण - यह संस्करण किसके विरुद्ध है? – goric

+1

क्या यह वास्तव में आपका कोड संरचित किया गया है? मूल्य 'स्वर' को दूसरे उदाहरण में उठाया जाना चाहिए या अन्यथा इसे केवल 5 बार '! =' के रूप में निष्पादित किया जाएगा। इस समस्या के लिए @EricLippert द्वारा –

उत्तर

57

आप एक सी # संस्करण की तुलना में कम 5.0 (जहां यह तय किया गया था) का उपयोग कर रहे हैं, यह कारण है।
क्योंकि लिंक को स्थगित निष्पादन का उपयोग करना पसंद है, इसलिए इस संदर्भ का मान तब तक नहीं पढ़ा जाता जब तक कि क्वेरी निष्पादित नहीं हो जाती (इसे पुनरावृत्त करके), जो foreach लूप समाप्त होने के बाद है। उस बिंदु पर, vowel का सबसे हालिया मूल्य u है, यही कारण है कि आपको अप्रत्याशित आउटपुट मिलता है।

आप मूल्य को अन्य अस्थायी चर (या सी # 5.0 में अपग्रेड करके) प्रतिलिपि बनाकर प्राप्त कर सकते हैं।

इस प्रयास करें:

बंद करने के बारे
query = "Probably what you might expect"; 

foreach (char vowel in "aeiou") { 
    char currentVowel = vowel; 
    query = query.Where (c => c != currentVowel); 
} 
+0

बस उत्सुक, सी # को कब ठीक किया गया? मैं इस फिक्स के बारे में कहां पढ़ सकता हूं? धन्यवाद। –

+3

ओह, [मैं देखता हूं] (http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-cononsidered-harmful.aspx), सी # 5 में –

+2

आश्चर्य है कि यह .NET 4.5 में "निश्चित" क्यों किया गया है। चूंकि LINQ परिभाषित किया गया है-परिभाषा द्वारा निष्पादन, मुझे नहीं लगता कि पुराने व्यवहार को क्यों संशोधित करें, जो वास्तव में अधिक सही है। – Teejay

11

पढ़ें। यदि आप .NET 4.0 का उपयोग करते हैं और नीचे आपको अलग-अलग परिणाम मिलेंगे। .NET 4.5 में यह व्यवहार बदल गया है (निश्चित)। यह भी देखें कि कंपाइलर foreach का विस्तार कैसे करता है।

+0

इस आलेख के लिए http://msmvps.com/blogs/kathleen/archive/2012/07/03/lifting-foreach-breaking-change-in-visual-studio-2012.aspx यह वीएस में एक बदलाव प्रतीत होता है सी # 5 की बजाय 2012 कंपाइलर। असल में, मैंने फ्रेमवर्क 3.5 पर वीबी के साथ कोशिश की और यह नया * अपेक्षित * परिणाम देता है। भावी पाठकों को भ्रमित न करने के लिए कृपया अपना उत्तर संशोधित करें। – Teejay

+1

@ तिजय इस व्यवहार को सी # 5.0 विनिर्देशन में वर्णित किया गया है। इसके अलावा कंपाइलर .NET ढांचे का हिस्सा हैं। –

+1

शायद। लेकिन आपने लिखा "* यदि आप .NET 4.0 का उपयोग करते हैं और नीचे आपको अलग-अलग परिणाम मिलेंगे।" *। यह सच नहीं है। बस 3.5 पर भी कोशिश की और यह नए 4.5 के रूप में व्यवहार करता है। – Teejay

13

ऐसा इसलिए है क्योंकि आप vowel चर पर एक बंद बनाते हैं, जो समय में परिवर्तन करता है। अपने मान को एक अलग चर में स्टोर करें और यह काम करेगा:

query = "Not what you might expect"; 

foreach (char vowel in "aeiou") 
{ 
    var current = vowel; 
    query = query.Where (c => c != current); 
} 
संबंधित मुद्दे