2010-09-17 13 views
9

में उपज रिटर्न स्टेटमेंट के बीच सटीक अंतर क्या है वर्तमान में मैं कुछ पुस्तकालयों के साथ काम कर रहा हूं जो इटरेटर के माध्यम से स्थगित निष्पादन लागू कर रहे हैं। कुछ परिस्थितियों में मुझे प्राप्तकर्ता पुनरावर्तक को "आगे" करने की आवश्यकता है। अर्थात। मुझे बुलाए गए विधि से IEnumerable<T> उदाहरण प्राप्त करना होगा और इसे तुरंत वापस करना होगा।एक आईनेमरेबल इंस्टेंस लौटने और सी #

अब मेरा प्रश्न: क्या प्राप्तकर्ता IEnumerable<T> को वापस लाने या लूप के माध्यम से इसे फिर से प्राप्त करने के बीच कोई प्रासंगिक अंतर है?

IEnumerable<int> GetByReturn() 
{ 
    return GetIterator(); // GetIterator() returns IEnumerable<int> 
} 
// or: 
IEnumerable<int> GetByReYielding() 
{ 
    for(var item in GetIterator()) // GetIterator() returns IEnumerable<int> 
    { 
     yield return item; 
    } 
} 
+2

पुन: उपज का लाभ क्या है? यदि आप वस्तुओं पर कुछ कार्रवाई करना चाहते हैं, तो आप चारों ओर लूपिंग नहीं करेंगे, है ना? यदि नहीं, तो छोटे-कोड-संस्करण का उपयोग क्यों न करें? –

+0

मैं अपने प्रयोगों (और आईएल निरीक्षण) से निष्कर्ष निकाला हूं, कि GetByReYielding() का निष्पादन स्वयं को स्थगित कर दिया जाएगा (GetIterator() काम से मुक्त), लेकिन GetByReturn() का निष्पादन नहीं है। बस इतना ही। – Nico

उत्तर

1

कोई भी प्रासंगिक अंतर नहीं है (से प्रदर्शन) दोनों के बीच) क्योंकि आप GetIterator() से गणक के साथ कुछ भी नहीं कर रहे हैं। अगर आप गणनाकर्ता के साथ कुछ करने जा रहे थे, तो इसे फिर से उपज करने के लिए केवल समझदारी होगी।

1

मुझे कोड सूजन के अलावा कोई प्रासंगिक अंतर नहीं दिख रहा है।

3

वे अलग हैं। उदाहरण के लिए, यदि GetIterator() रूप में घोषित किया:

IEnumerable<int> GetIterator() { 
    List<int> result = new List<int>(); 
    for(int i = 0; i < 1000; i++) { 
     result.Add(i); 
    } 
    return result; 
} 

आप फिर से उपज, GetIterator() ऐसा नहीं करते हैं और पाश तुरंत मार डाला गया। इसलिए, उत्तर इस बात पर निर्भर करता है कि आप GetIterator() को कैसे कार्यान्वित करते हैं। यदि यह निश्चित है कि GetIterator() उपज होगा, तो इसका कोई पुन: उपज नहीं है।

+2

भले ही वह एक पुनरावर्तक का उपयोग करता है, फिर भी यह पहले _yield_ से पहले पूरी सूची के माध्यम से लूप होगा। –

0

एक प्रासंगिक अंतर है।

GetByReYielding() का निष्पादन स्थगित तरीके से निष्पादित किया जाएगा (क्योंकि यह एक पुनरावर्तक ब्लॉक है)। यदि आपने GetByReturn() या GetByReYielding() में पैरामीटर का उपयोग किया है और उस पैरामीटर को शून्यता के लिए रनटाइम पर चेक किया है (या कोई अन्य सत्यापन किया है), तो यह चेक तत्काल किया जाएगा जब GetByReturn() को कॉल किया जाता है लेकिन तत्काल नहीं जब GetByReYielding() को कॉल किया जाता है ! GetByReYielding() में प्रमाणीकरण स्थगित तरीके से किया जाएगा, जब परिणाम पुनरावृत्त हो जाएगा। - यह अक्सर, "बहुत देर हो चुकी है"। यहाँ देखें:

// Checks parameters early. - Fine. The passed argument will be checked directly when 
// GetByReturn() is called. 
IEnumerable<int> GetByReturn(IEnumerable<int> sequence) 
{ 
    if(null == sequence) 
    { 
     throw new ArgumentNullException("sequence"); 
    } 

    return GetIterator(); 
} 
// Checks parameters in a deferred manner. - Possibly not desired, it's "too" late. I.e.     // when the  
// result is iterated somewhere in a completely different location in your code the 
// argument passed once will be checked. 
IEnumerable<int> GetByReYielding(IEnumerable<int> sequence) 
{ 
    if(null == sequence) 
    { 
     throw new ArgumentNullException("sequence"); 
    } 

    for(var item in GetIterator()) 
    { 
     yield return item; 
    } 
} 

श्री स्कीट http://msmvps.com/blogs/jon_skeet/archive/2010/09/03/reimplementing-linq-to-objects-part-2-quot-where-quot.aspx में इस अवधारणा की व्याख्या की। नेट क्वेरी में प्रदान किए गए मानक क्वेरी ऑपरेटर गैर-स्थगित रैपर फ़ंक्शंस (उदा। कहां()) का उपयोग करते हैं जो पैरामीटर जांचते हैं और फिर कोर इटरेटर फ़ंक्शन को कॉल करते हैं (जैसा कि मैंने GetByReturn() के कार्यान्वयन में दिखाया है)।

मुझे उम्मीद है कि इससे मदद मिलती है।

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