2009-12-28 13 views
13

सी # उपज कीवर्ड एक ट्यूटोरियल के माध्यम से कार्य करना के दिलचस्प उपयोग (व्यावसायिक ASP.NET MVC बेवकूफ रात का भोजन), मैं कोड के इस स्निपेट में आए yield, लेकिन मुझे लगता है कि मेरी समझ अभी भी थोड़ा आलसी है। क्या यह करने के लिए लगता है कि वास्तव में साइकिल चलाना जब तक यह बिल्कुल आवश्यक है कर के बिना एक संग्रह में आइटम के माध्यम से साइकिल चालन की अनुमति देता है एक वस्तु बनाने के लिए है।में बेवकूफ डिनर ट्यूटोरियल

यह उदाहरण एक छोटे से मेरे लिए अजीब है, हालांकि है। क्या मुझे लगता है कि यह कर रहा है किसी भी RuleViolation उदाहरणों के निर्माण में देरी जब तक प्रोग्रामर वास्तव में संग्रह या तो for each या .ElementAt(2) की तरह एक LINQ विस्तार विधि का उपयोग कर में किसी विशिष्ट आइटम का अनुरोध करता है।

  1. जब if बयानों की सशर्त भागों का मूल्यांकन मिलता है:

    इसके अलावा, हालांकि, मैं कुछ प्रश्न हैं? जब GetRuleViolations() कहा जाता है या जब गणना करने योग्य वास्तव में पुनरावृत्त होता है? दूसरे शब्दों में, Titlenull से Really Geeky Dinner में GetRuleViolations() पर कॉल करने के समय और जब मैं वास्तव में इसे पुन: सक्रिय करने का प्रयास करता हूं, तो RuleViolation("Title required", "Title") बनाया जाएगा या नहीं?

  2. क्यों yield break; आवश्यक है? यह वास्तव में यहाँ क्या कर रहा है?

  3. मान लीजिए कि Title शून्य या खाली है करते हैं। अगर मैं GetRuleViolations() पर कॉल करता हूं तो परिणामस्वरूप दो बार परिणामस्वरूप गणना करने योग्य दो बार, new RuleViolation("Title required", "Title") कितनी बार कॉल किया जाएगा?

+3

.Net संकलक इस सिंटेक्टिक चीनी को एक अधिक बेस्टर्डीकृत रूप में बदल देता है। नमूना संकलित करें और फिर परावर्तक में आईएल लोड करें। आपको यह समझने के लिए अबाउट होना चाहिए कि वहां क्या हो रहा है। –

उत्तर

17

एक समारोह है कि yield आदेशों में शामिल है एक सामान्य कार्य से अलग व्यवहार किया जाता है। दृश्यों के पीछे क्या हो रहा है जब उस समारोह को कहा जाता है, यह है कि एक अज्ञात प्रकार विशिष्ट IEnumerable फ़ंक्शन के प्रकार का निर्माण होता है, फ़ंक्शन उस प्रकार का ऑब्जेक्ट बनाता है और इसे वापस करता है। अज्ञात वर्ग में तर्क होता है जो IEnumerable.MoveNext को हर बार के लिए अगली yield कमांड तक फ़ंक्शन के शरीर को निष्पादित करता है। यह थोड़ा भ्रामक है, फ़ंक्शन का शरीर सामान्य बैच की तरह एक बैच में निष्पादित नहीं होता है, बल्कि टुकड़ों में, प्रत्येक टुकड़ा तब निष्पादित होता है जब गणनाकर्ता एक कदम आगे बढ़ता है।

के साथ संबंध है

अपने प्रश्नों के:

  1. जैसा कि मैंने कहा, प्रत्येक if निष्पादित हो जाता है जब आप अगले तत्व पुनरावृति।
  2. yield break वास्तव में ऊपर दिए गए उदाहरण में आवश्यक नहीं है। यह क्या करता है यह गणना को समाप्त करता है।
  3. प्रत्येक बार जब आप गणना करने के लिए पुनरावृत्त करते हैं, तो आप कोड को फिर से निष्पादित करने के लिए मजबूर करते हैं। प्रासंगिक रेखा पर ब्रेकपॉइंट रखें और अपने लिए परीक्षण करें।
+0

+1 वास्तव में स्पष्ट और सहायक उत्तर, धन्यवाद। यदि आपको कोई फर्क नहीं पड़ता है तो बस एक मामूली अनुवर्ती प्रश्न: क्या आप एक ऐसे उदाहरण के बारे में सोच सकते हैं जहां 'उपज ब्रेक' * आवश्यक है? – devuxer

+1

मामूली स्पष्टीकरण - आपका मतलब है 'आईन्यूमेरेटर []' कुछ स्थानों पर जहां आप 'आईनेमेरेबल [] 'कहते हैं। –

+0

तो उदाहरण में 'उपज ब्रेक' आवश्यक है, क्योंकि यदि कोई 'नियम उल्लंघन' नहीं बनाया गया है, तो यह अपवाद फेंक देगा, है ना? – Ronald

6

1) इस सरल उदाहरण लें:

public void Enumerate() 
{ 
    foreach (var item in EnumerateItems()) 
    { 
     Console.WriteLine(item); 
    } 
} 

public IEnumerable<string> EnumerateItems() 
{ 
    yield return "item1"; 
    yield return "item2"; 
    yield break; 
} 

हर बार जब आप IEnumerator से MoveNext() फोन yield बिंदु और कोड के अगले निष्पादन योग्य लाइन पर ले जाता है से कोड रिटर्न।

2) yield break;IEnumerator बताएगा कि गणना करने के लिए और कुछ भी नहीं है।

3) प्रति गणना एक बार।

का उपयोग कर yield break;

public IEnumerable<string> EnumerateUntilEmpty() 
{ 
    foreach (var name in nameList) 
    { 
     if (String.IsNullOrEmpty(name)) yield break; 
     yield return name; 
    }  
} 
+0

"3) एक बार" के बारे में निश्चित है? जहां तक ​​मैं समझता हूं कि यह हर बार पुनर्मूल्यांकन किया जाता है (यहां दो अन्य उत्तरों देखें)। –

+0

मैंने इसे स्पष्ट किया। – ChaosPandion

+0

यदि आप कोई सूची बनाते हैं, तो फिर भी इसे फिर से क्यों न करें? 'उपज' तरीका आपको स्पष्ट रूप से सूची बनाने के लिए सक्षम बनाता है। उदाहरण के लिए आपके मामले में: सार्वजनिक आईनेमेरेबल अंकुश() { उपज वापसी "item1"; उपज वापसी "item2"; } –

2

लघु संस्करण:

1: उपज जादू "बंद करो और बाद में देखें" है कीवर्ड है, तो "सक्रिय" एक के सामने बयान मूल्यांकन किया गया है यदि।

2: उपज को तोड़ने स्पष्ट रूप से समाप्त हो जाती है गणन (लगता है "तोड़" एक स्विच मामले में)

3: हर बार। आप परिणाम को कैश कर सकते हैं, बेशक, इसे एक सूची में बदलकर और बाद में इसे फिर से चालू कर सकते हैं।

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