विशेष कोड नमूना आप देख रहे हैं परिवर्तनों की एक श्रृंखला शामिल है (श्रृंखला, नहीं भाग 4 के भाग 1 को इंगित करने के संपादित)। कृपया ध्यान दें कि यह एल्गोरिदम का अनुमानित विवरण है। कंपाइलर द्वारा उपयोग किए जाने वाले वास्तविक नाम, और जो सटीक कोड उत्पन्न होता है वह अलग हो सकता है। फिर विचार वही है, हालांकि।
var enumerator = y.GetEnumerator();
while (enumerator.MoveNext())
{
var x = enumerator.Current;
//body
}
if (y != null)
{
enumerator.Dispose();
}
दूसरा परिवर्तन समारोह शरीर में सभी उपज वापसी बयान पाता है: इस कोड में
foreach (var x in y)
{
//body
}
:
पहले परिवर्तन "foreach" परिवर्तन है, जो इस कोड को बदल देती है , प्रत्येक (एक राज्य मूल्य) के लिए एक संख्या निर्दिष्ट करता है, और उपज के ठीक बाद एक "गोटो लेबल" बनाता है।
तीसरा परिवर्तन विधि निकाय में सभी स्थानीय चर और कार्य तर्क को बंद करने वाले ऑब्जेक्ट में ले जाता है।
अपने उदाहरण में कोड को देखते हुए कि इस के समान दिखेगा:
class ClosureEnumerable : IEnumerable<string>
{
private IEnumerable<string> args;
private ClassType originalThis;
public ClosureEnumerator(ClassType origThis, IEnumerable<string> args)
{
this.args = args;
this.origianlThis = origThis;
}
public IEnumerator<string> GetEnumerator()
{
return new Closure(origThis, args);
}
}
class Closure : IEnumerator<string>
{
public Closure(ClassType originalThis, IEnumerable<string> args)
{
state = 0;
this.args = args;
this.originalThis = originalThis;
}
private IEnumerable<string> args;
private IEnumerator<string> enumerator2;
private IEnumerator<string> argEnumerator;
//- Here ClassType is the type of the object that contained the method
// This may be optimized away if the method does not access any
// class members
private ClassType originalThis;
//This holds the state value.
private int state;
//The current value to return
private string currentValue;
public string Current
{
get
{
return currentValue;
}
}
}
विधि शरीर फिर मूल विधि से ले जाया जाता है "बंद" के अंदर एक विधि MoveNext कहा जाता है, जो एक bool रिटर्न के लिए , और IENumerable.MoveNext लागू करता है। किसी भी स्थानीय लोगों के लिए किसी भी पहुंच को "इस" के माध्यम से भेजा जाता है, और किसी भी वर्ग के सदस्यों के लिए किसी भी पहुंच को इस माध्यम से रूट किया जाता है।
किसी भी "उपज वापसी expr" में अनुवाद किया है:
state = -1;
return false;
एक "निहित" के अंत में उपज तोड़ बयान नहीं है:
currentValue = expr;
state = //the state number of the yield statement;
return true;
किसी भी उपज तोड़ बयान में अनुवादित किया गया समारोह। तब एक स्विच स्टेटमेंट उस प्रक्रिया की शुरुआत में पेश किया जाता है जो राज्य संख्या को देखता है और संबंधित लेबल पर कूदता है।
मूल विधि तो कुछ इस तरह में अनुवाद किया जाता है:
IEnumerator<string> strings(IEnumerable<string> args)
{
return new ClosureEnumerable(this,args);
}
तथ्य यह है कि विधि के राज्य सब एक वस्तु में और MoveNext विधि एक स्विच बयान का उपयोग करता है धकेल दिया जाता है/राज्य चर क्या है इटेटरेटर को व्यवहार करने की इजाजत देता है जैसे अगली बार "मूवनेक्स्ट" कहा जाता है, तो पिछले "उपज रिटर्न" कथन के तुरंत बाद नियंत्रण को बिंदु पर वापस भेज दिया जा रहा है।
हालांकि, यह इंगित करना महत्वपूर्ण है कि सी # कंपाइलर द्वारा उपयोग किया जाने वाला परिवर्तन ऐसा करने का सबसे अच्छा तरीका नहीं है। रिकर्सिव एल्गोरिदम के साथ "उपज" का उपयोग करने की कोशिश करते समय यह खराब प्रदर्शन से पीड़ित है।
http://research.microsoft.com/en-us/projects/specsharp/iterators.pdf
यह यदि आप इसे अभी तक नहीं पढ़ा है पढ़ने लायक है: वहाँ एक अच्छा कागज कि इस यहाँ करने के लिए एक बेहतर तरीका की रूपरेखा है।
वाह। उत्कृष्ट और व्यापक उत्तर। काश मैं इसे एक से अधिक बार वोट दे सकता हूं। –