2010-11-12 11 views
5

मैं अपने सिर को लपेटने की कोशिश कर रहा हूं कि सी # कंपाइलर क्या करता है जब मैं linq विधियों को चेन कर रहा हूं, खासकर जब एक ही विधि को कई बार चेन करना।सी # कंपाइलर चेनिंग linq विधियों के साथ कैसे व्यवहार करता है

सरल उदाहरण: मान लें कि मैं दो स्थितियों के आधार पर इनट्स के अनुक्रम को फ़िल्टर करने की कोशिश कर रहा हूं।

सबसे स्पष्ट बात करने के लिए कुछ इस तरह है:

IEnumerable<int> Method1(IEnumerable<int> input) 
{ 
    return input.Where(i => i % 3 == 0 && i % 5 == 0); 
} 

लेकिन हम भी प्रत्येक में एक भी शर्त के साथ जहां तरीकों श्रृंखला सकता है,:

IEnumerable<int> Method2(IEnumerable<int> input) 
{ 
    return input.Where(i => i % 3 == 0).Where(i => i % 5 == 0); 
} 

मैं एक था प्रतिबिंब में आईएल देखें; यह स्पष्ट रूप से दो विधियों के लिए अलग अलग है, लेकिन यह आगे का विश्लेषण पल :)

मैं पता लगाने के लिए चाहते हैं पर अपने ज्ञान से परे है:
क) क्या संकलक प्रत्येक उदाहरण में अलग ढंग से करता है, और क्यों।
ख) किसी भी प्रदर्शन निहितार्थ देखते हैं (माइक्रो-अनुकूलन की कोशिश नहीं;! बस जिज्ञासु)

उत्तर

9

का जवाब (क) कम है, लेकिन मैं नीचे और अधिक विस्तार में जाने देंगे:

संकलक वास्तव में श्रृंखलन नहीं करता है - यह सामान्य के माध्यम से, क्रम में क्या होता है वस्तुओं का संगठन! पहली नज़र में जो दिखाई दे सकता है उससे कहीं कम जादू है - जॉन स्कीट recently completed the "Where clause" step अपनी ब्लॉग श्रृंखला में, पुनः-कार्यान्वयन LINQ से ऑब्जेक्ट्स में। मैं उस के माध्यम से पढ़ने की सिफारिश करेंगे। यह रिटर्न एक नया WhereEnumerable वस्तु दो बातें है कि हर बार जब आप Where विस्तार विधि कॉल, - पिछले IEnumerable (एक आप Where पर कहा जाता है) के लिए एक संदर्भ है, और:

बहुत ही कम शब्दों में, क्या होता है यह है आपके द्वारा प्रदान किया गया लैम्ब्डा।

जब आप (जो बाद में अपने कोड में नीचे एक foreach में उदाहरण के लिए,) इस WhereEnumerable से अधिक पुनरावृत्ति शुरू, आंतरिक रूप से यह बस पर IEnumerable कि यह संदर्भित है पुनरावृत्ति शुरू होता है।

"यह foreach बस मेरी अनुक्रम में अगले तत्व के लिए मुझसे पूछा, तो मैं चारों ओर मोड़ रहा हूँ और में अपने अनुक्रम अगले तत्व के लिए आप पूछ"।

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

यह तब तक होता रहता है जब तक कि MoveNext झूठी रिटर्न न हो, जिसका अर्थ है कि गणना पूर्ण हो गई है और कोई और तत्व नहीं हैं।

(ख), वहाँ हमेशा एक फर्क उत्तर देने के लिए, लेकिन यहाँ यह अभी तक बहुत से परेशान करने के लिए तुच्छ है। इसके बारे में चिंता न करें :)

+0

अच्छा जवाब। हमें स्टैक ओवरफ्लो पर इस तरह की अधिक सामग्री चाहिए। –

1
  1. पहले एक इटरेटर का उपयोग करेगा, दूसरा दो का प्रयोग करेंगे। यही है, पहले एक चरण के साथ एक पाइपलाइन सेट करता है, दूसरे में दो चरण शामिल होंगे।

  2. दो पुनरावृत्तियों के लिए थोड़ा सा प्रदर्शन नुकसान होता है।