2009-10-20 21 views
10

जब मैं एक कोड ब्लॉककाम कर रहे पैटर्न

static void Main() 
{ 

    foreach (int i in YieldDemo.SupplyIntegers()) 
    { 
    Console.WriteLine("{0} is consumed by foreach iteration", i); 
    } 
} 


class YieldDemo 
    { 
    public static IEnumerable<int> SupplyIntegers() 
    { 
     yield return 1; 
     yield return 2; 
      yield return 3; 
     } 
    } 

मैं सिद्धांत उपज वापसी के पीछे व्याख्या कर सकते हैं के रूप में

  1. मुख्य() SupplyIntegers()
  2. |1| |2| |3| are stored in contiguous memory block.Pointer of "IEnumerator" Moves to |1|
  3. कॉल
  4. आपूर्ति इंटेगर() से मुख्य() तक नियंत्रण रिटर्न।
  5. मुख्य() मूल्य
  6. पॉइंटर मूव्स | 2 |, और इसी तरह से प्रिंट करता है।

स्पष्टीकरण:

(1) आम तौर पर हम अंदर एक function.How सी # व्यवहार करता है जब कई उपज वापसी, उपज वापसी, ... बयान मौजूद हैं एक वैध वापसी कथन अनुमति दी है होगा ?

(2) एक बार वापसी का सामना करने के बाद आपूर्तिइंटर() पर नियंत्रण के लिए फिर से कोई रास्ता नहीं है, यदि अनुमति है तो यील्ड फिर से 1 से शुरू नहीं होगा? मेरा मतलब उपज वापसी 1 है?

+0

पुन एक किताब के बारे में पूछ: गहराई में सी # (मैनिंग, स्कीट), अध्याय 6. यह निशुल्क नमूना अध्याय है, और इसमें इटरेटर ब्लॉक शामिल हैं। यह बिल्कुल शुरुआती सी # पुस्तक नहीं है (इससे दूर), लेकिन आप इस विषय पर एक बेहतर संदर्भ खोजने के लिए संघर्ष करेंगे। –

+0

यदि विशेषाधिकारों को यह पूछने की अनुमति है कि "क्या आपने कोई पुस्तक नहीं लिखी है?" – user193276

+0

नहीं, मैंने नहीं किया है। मैं एक प्रकाशक के लिए कुछ प्रमाण-पढ़ता हूं, और मैं कभी-कभी अजीब लेख लिखता हूं, लेकिन मेरे द्वारा कोई पुस्तक नहीं। –

उत्तर

30

नहीं - इससे दूर; मैं तुम्हारे लिए एक लंबा हाथ लिखूंगा ... यह बहुत गड़बड़ है!


नोट यह भी मदद करता है अगर आप समझते हैं कि foreach वास्तव में है:

using(var iterator = YieldDemo.SupplyIntegers().GetEnumerator()) { 
    int i; 
    while(iterator.MoveNext()) { 
     i = iterator.Current; 
     Console.WriteLine("{0} is consumed by foreach iteration", i); 
    } 
} 

using System; 
using System.Collections; 
using System.Collections.Generic; 
static class Program 
{ 
    static void Main() 
    { 

     foreach (int i in YieldDemo.SupplyIntegers()) 
     { 
      Console.WriteLine("{0} is consumed by foreach iteration", i); 
     } 
    } 
} 

class YieldDemo 
    { 

    public static IEnumerable<int> SupplyIntegers() 
    { 
     return new YieldEnumerable(); 
     } 
    class YieldEnumerable : IEnumerable<int> 
    { 
     public IEnumerator<int> GetEnumerator() 
     { 
      return new YieldIterator(); 
     } 
     IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } 
    } 
    class YieldIterator : IEnumerator<int> 
    { 
     private int state = 0; 
     private int value; 
     public int Current { get { return value; } } 
     object IEnumerator.Current { get { return Current; } } 
     void IEnumerator.Reset() { throw new NotSupportedException(); } 
     void IDisposable.Dispose() { } 
     public bool MoveNext() 
     { 
      switch (state) 
      { 
       case 0: value = 1; state = 1; return true; 
       case 1: value = 2; state = 2; return true; 
       case 2: value = 3; state = 3; return true; 
       default: return false; 
      } 
     } 
    } 
} 

आप देख सकते हैं, यह एक राज्य मशीन इटरेटर में, राज्य के साथ बनाता है मशीन MoveNext द्वारा प्रगति की गई। मैंने state फ़ील्ड के साथ पैटर्न का उपयोग किया है, क्योंकि आप देख सकते हैं कि यह अधिक जटिल इटरेटर्स के लिए कैसे काम करेगा।

महत्वपूर्ण बात:

  • अपने iterator ब्लॉक में किसी भी चर राज्य मशीन
  • पर खेतों बन अगर आप (using सहित) एक finally ब्लॉक है, यह Dispose()
  • के कुछ भागों में चला जाता है yield return के लिए अग्रणी कोड case (लगभग)
  • yield breakबन गया(या इसी तरह)

जिस तरह से सी # कंपाइलर यह बहुत जटिल है, लेकिन यह इटरेटर को हवा लिखता है।

+2

से मेल खाता है अविश्वसनीय है कि लोग वास्तव में एक उपयोगी उत्तर देने से पहले इसे ऊपर उठा रहे हैं। – Joren

+1

@ जोरेन: यह बताता है कि मार्क कितना अच्छा है। ;) उत्कृष्ट जवाब मार्क! – jrista

+1

यह वास्तव में सरल है, जब मार्क कहता है कि वह कुछ पोस्ट करने जा रहा है, तो आप काफी शर्त लगा सकते हैं कि यह सही होगा। – kemiller2002

3

यह सिर्फ एक वाक्य रचना चीनी वर्तमान की तुलना में IEnumarable वर्ग GetEnumerator रिटर्न जिनमें से कि IEnumerator, आप .net परावर्तक या ILDASM द्वारा कि जादू वर्गों देख सकते हैं उत्पन्न करता है, .net आप के लिए IEnumerator वर्ग उत्पन्न करता है और MoveNext लागू करता है, और तरीकों रीसेट,।

भी देखें here

1
संक्षेप में

, (जबकि साल मार्क के लंबे समय से हाथ संस्करण के लिए प्रतीक्षा में) जब संकलक उपज बयान, पर्दे के पीछे यह आप के लिए एक कस्टम वर्ग का एक नया उदाहरण बनाता है एक अंतरफलक को लागू करता है कि देखता है IEnumerator कहा जाता है, जिसमें Current(), और MoveNext() विधियां हैं, और वर्तमान में पुनरावृत्ति प्रक्रिया में कहां हैं, इसका ट्रैक रखता है ... आपके उदाहरण के रूप में ऊपर दिए गए मामले में, यह सूची में मूल्यों का ट्रैक भी रखेगा।

2

बस शब्दों में कहें, इटरेटर ब्लॉक (या yield कथन के साथ विधियां, यदि आप कर सकते हैं) संकलक द्वारा संकलक द्वारा जेनरेट की गई कक्षा में परिवर्तित हो जाते हैं। यह वर्ग IEnumerator लागू करता है और yield कथन उस वर्ग के लिए 'राज्य' में परिवर्तित हो जाता है।

उदाहरण के लिए, इस:

yield return 1; 
yield return 2; 
yield return 3; 

को कुछ इसी तरह के रूप में तब्दील हो सकता है:

switch (state) 
{ 
    case 0: goto LABEL_A; 
    case 1: goto LABEL_B; 
    case 2: goto LABEL_C; 
} 
LABEL_A: 
    return 1; 
LABEL_B: 
    return 2; 
LABEL_C: 
    return 3; 

इटरेटर खंड हैं निकाला राज्य मशीनों के रूप में देखा जा सकता है। यह कोड IEnumerator के तरीकों से लागू किया जाएगा।

-2

क्या आपको स्कूल में श्रुतलेख याद है? मान लें कि हमारे पास पांच शब्द हैं, जो अंग्रेजी शब्दों के श्रुतलेख के लिए आते हैं। हमारे पास ब्लैकबोर्ड में लिखे गए शब्दों की एक सूची है। बच्चे ब्लैकबोर्ड नहीं देख सकते लेकिन शिक्षक इसे देख सकते हैं। कृपया ध्यान दें कि, शब्दों को सभी बच्चों के लिए एक ही क्रम में दिया जाना चाहिए। प्रत्येक बच्चे को एक अलग शिक्षक द्वारा भाग लिया जाता है।

ब्लैकबोर्ड: अमेरिका के
      संयुक्त राज्य अमेरिका
      यूनाइटेड किंगडम
      भारत
प्रश्न
एक। ग्राहक कौन हैं?
बी। डेटा प्रदाता कौन है?
सी। संग्रह (Iterating या गणनाकर्ता) संग्रह कौन है?
उत्तर:
ए। बच्चे
बी। ब्लैकबोर्ड
सी। शिक्षक

सी # दृष्टि में:

ब्लैकबोर्ड - डेटा प्रदाता - IEnumerable
शिक्षक - इटरेटर - राज्य मशीन
बच्चे - ग्राहक - foreach

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