2012-12-19 56 views
5

शामिल नहीं हो सकता है मान लें कि मेरे पास निम्न विधि है। कुछ मेंएक इटरेटर ब्लॉक से एक तत्व को लौटाना - इटरेटर में रिटर्न स्टेटमेंट

public IEnumerable<ValidationResult> Validate(UserLoginCommand command) 
    { 
     User user = userRepository.Get(u => u.Email == command.UserEmail); 
     if(user != null) 
     { 
      if(!user.Activated) 
      { 
       return new IEnumerable<ValidationResult>() {new ValidationResult("NotActived", Resources.UserNotActivated)}; 
      } 

      if(user.IsPasswordIncorrent) 
      { 

       yield return new ValidationResult("IncorrectPassword", Resources.IncorrentPassword); 

      } 

     } 
    } 

वास्तविक स्थिति वास्तव में थोड़ा अधिक जटिल है लेकिन मैंने चित्रण उद्देश्यों के लिए बहुत कुछ छोड़ दिया है।

बिंदु कुछ मामलों में है, मैं कई त्रुटियों का संग्रह करते रहना iterator करना चाहते हैं ... लेकिन अन्य मामलों में एक गंभीर त्रुटि है और मैं केवल एक ही त्रुटि वापस चाहते हैं, लेकिन यह मुझे नहीं दूँगी:

Iterator cannot contain return statement 

मुझे क्या करना चाहिए?

+2

मुझे लगता है कि त्रुटि संदेश बहुत स्पष्ट है। आप 'उपज' और 'वापसी' मिश्रण नहीं कर सकते हैं, क्योंकि फ़ंक्शन निष्पादन स्थगित होने तक स्थगित कर दिया जाता है। मैं सुझाव देता हूं कि 'उपज' से छुटकारा पाएं और बस अपनी खुद की गणना बनाएं। मुझे उम्मीद है कि जॉन स्कीट या एरिक लिपर्ट यहां पर चिल्लाएंगे कि क्यों संकलक इस मामले को संभाल नहीं सकता है। –

उत्तर

10

तुम सिर्फ आकार एक का एक संग्रह लौटना चाहते हैं, तो आप ऐसा कर सकते हैं:

if(!user.Activated) 
{ 
    yield return new ValidationResult("NotActived", Resources.UserNotActivated); 
    yield break; 
} 
+0

धन्यवाद, यह आवश्यक सरल समाधान है। – parliament

3

क्या वापसी का बयान वास्तव में उपज नहीं होना चाहिए?

yield return ValidationResult("NotActived", Resources.UserNotActivated); 

तुम सच में एक संग्रह वापस जाने के लिए की जरूरत है, तो आप कर सकते हैं yield return एक संग्रह है, भी (जैसे तुम्हारे पास है), यह सिर्फ आवश्यक नहीं है, क्योंकि आप केवल एक है।

इसके अलावा, ऐसा होता है कि आप स्पष्ट रूप से गणना बंद करना चाहते हैं, तो आप उपयोग कर सकते हैं yield break;

3

के रूप में त्रुटि संदेश द्वारा इंगित किया गया है, आप एक विधि में yield return कथन और return कथन मिश्रण नहीं कर सकते हैं।

आप दो सामान्य दृष्टिकोण है:

  1. विधि बेसब्री से मूल्यांकन किया जाना चाहिए; आपको सभी return कथन का उपयोग करना चाहिए, सभी yield कथन में कथन को परिवर्तित करने का एक तरीका खोजें।
  2. विधि को स्थगित निष्पादन का उपयोग करना चाहिए, सभी return कथन yield कथनों में बदलने के लिए एक तरीका खोजें।

आपके मामले में, यह शायद # 2 है, लेकिन अन्य स्थितियों में या तो उचित हो सकता है।

अब, बारी एक एक return में yield रहे हैं:

किसी प्रकार का एक संग्रह में एक तत्व लपेट और कहा कि वापसी:

return new[]{ someItemToReturn }; 

या

return Enumerable.Repeat<T>(someItemToReturn, 1); 

अब, return को yield में कैसे बदलें:

foreach(var item in collectionYouWereReturning) 
    yield return item; 

आप yield break; का उपयोग यह संकेत करने के लिए कर सकते हैं कि अनुक्रम समाप्त हो गया है, भले ही विधि यह प्राकृतिक अंत तक नहीं पहुंच पाई हो। ध्यान दें कि yield break; बहुत ही कम इस्तेमाल किया जाना चाहिए। इसका उपयोग करने से कोड गंध बहुत अधिक होगी (लेकिन ऐसा लगता है कि यह उचित होगा)।

अब, आदर्श रूप में, हमारे पास yield foreach कुछ प्रकार का कीवर्ड होगा ताकि आप एक इटरेटर ब्लॉक के अंदर एक संग्रह प्राप्त कर सकें, लेकिन अभी तक इस तरह के कोई भी कीवर्ड भाषा में नहीं जोड़ा गया है।

+0

प्रतिक्रिया के लिए धन्यवाद, मैंने कुछ उपयोगी चीजें सीखी हैं जो भविष्य में उपयोगी होंगी लेकिन इस मामले में मैंने वही पैटर्न रखना पसंद किया जो मैंने हर जगह इस्तेमाल किया (उपज वापसी) लेकिन असाधारण मामलों में केवल एक ही तत्व लौटाएं। पॉल फिलिप्स का जवाब सरल और काम था। निश्चित रूप से उपरोक्त। – parliament