2012-04-11 19 views
5

के अंत तक पर मान जोड़कर मैं सिर्फ पता चला के बारे में yield return, मैं वास्तव में अच्छा लगता है। मैं इस तरह एक विधि में इसका इस्तेमाल करते हैं:उपज वापसी जब एक मौजूदा IEnumerable

public IEnumerable<ValidationResult> Validate(ValidationContext vc) 
{ 
    if (Name == "Arbitary") 
     yield return new ValidationResult("Bad Name.", new[] { "Name" }); 
    else if (Email == "BadEmail") 
     yield return new ValidationResult("Bad Email.", new [] {"Email" }); 
    // further rules follow. 
} 

हालांकि, मैं इस पद्धति को बदलने के लिए एक बच्चे विधि से कुछ ValidationResults लौटना ही होगा। yield का उपयोग कर के बिना, कोड इस तरह दिखेगा:

public override IEnumerable<ValidationResult> Validate(ValidationContext vc) 
{ 
    // TryValidateObject fills the ICollection you pass it. 
    List<ValidationResult> retVal = new List<ValidationResult>(); 
    Validator.TryValidateObject(this, vc, retVal, true); 

    if (Name == "Arbitary") 
     retVal.Add(new ValidationResult("Bad Name.", new[] { "Name" })); 
    else if (Email == "BadEmail") 
     retVal.Add(new ValidationResult("Bad Email.", new[] { "Email" })); 

    return retVal; 
} 

यह yield का उपयोग कर इस पुनर्लेखन के लिए संभव है?

+0

ध्यान दें कि आप गलत वर्तनी है "मनमाना"। –

+0

@EricLippert हा, वास्तव में। मैं हर समय यह गलत वर्तनी करता हूं। इस मामले में हालांकि यह सिर्फ एक उदाहरण सत्यापन नियम है क्योंकि मैंने अभी तक 'असली' काम नहीं किया है। – Oliver

उत्तर

3

क्या आप इसे ढूंढ रहे हैं?

public override IEnumerable<ValidationResult> Validate(ValidationContext vc) 
{ 
    // TryValidateObject fills the ICollection you pass it. 
    List<ValidationResult> retVal = new List<ValidationResult>(); 
    Validator.TryValidateObject(this, vc, retVal, true); 
    foreach (var item in retVal) 
     yield return item; 
    if (Name == "Arbitary") 
     yield return new ValidationResult("Bad Name.", new[] { "Name" }); 
    else if (Email == "BadEmail") 
     yield return new ValidationResult("Bad Email.", new[] { "Email" });  
} 

यदि ऐसा है, तो मेरा मानना ​​है कि पहला संस्करण अच्छा दिखता है।

+0

इसके लिए धन्यवाद। क्या 'उपज ब्रेक' आवश्यक है? – Oliver

+0

नहीं, मैं इसे हटा दूंगा। –

2

ज़रूर। बस इसका उपयोग करें:

foreach (var item in retVal) { 
    yield return item; 
} 

इसके बाद, आप उपज रिटर्न के साथ भी जारी रख सकते हैं। इसलिए आप विधि को कॉल करने के बाद अपना रेटवेल वापस कर सकते हैं और फिर अपने पहले नमूने में जारी रख सकते हैं। इस तरह:

public override IEnumerable<ValidationResult> Validate(ValidationContext vc) 
{ 
    List<ValidationResult> retVal = new List<ValidationResult>(); 
    Validator.TryValidateObject(this, vc, retVal, true); 
    foreach (var item in retVal) { 
     yield return item; 
    } 

    if (Name == "Arbitary") 
     yield return new ValidationResult("Bad Name.", new[] { "Name" }); 
    else if (Email == "BadEmail") 
     yield return new ValidationResult("Bad Email.", new[] { "Email" }); 
    //... 
} 
2

अन्य समाधान अब तक तैनात अच्छे हैं। यहाँ अपनी समस्या को हल करने के लिए एक और तरीका है:

  • दो दृश्यों बनाएं
  • श्रेणीबद्ध उन्हें
  • वापसी संयोजन।

तो:

public override IEnumerable<ValidationResult> Validate(ValidationContext vc) 
{ 
    return ResultsFromValidator(vc).Concat(AdditionalResults()); 
} 
private IEnumerable<ValidationResult> ResultsFromValidator(ValidationContext vc) 
{ 
    List<ValidationResult> retVal = new List<ValidationResult>(); 
    Validator.TryValidateObject(this, vc, retVal, true); 
    return retVal; 
} 
private IEnumerable<ValidationResult> AdditionalResults() 
{ 
    if (Name == "Arbitrary") 
    yield return new ValidationResult("Bad Name.", new[] { "Name" }); 
    ... 
} 
संबंधित मुद्दे