2012-04-11 9 views
5

Ich habe gerade über yield return herausgefunden, scheint mir wirklich nett. Ich benutze es in einem Verfahren wie folgt aus:Renditerückgabe beim Anhängen von Werten an das Ende eines vorhandenen 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. 
} 

Ich brauche aber diese Methode ändern einige ValidationResults von einem Kind Methode zurückzukehren. Ohne yield zu verwenden, würde der Code wie folgt aussehen:

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; 
} 

Ist es möglich, dies mit yield neu zu schreiben?

+0

Beachten Sie, dass "willkürlich" falsch geschrieben haben. –

+0

@EricLippert Hah, tatsächlich. Ich buchstabiere das die ganze Zeit falsch. In diesem Fall handelt es sich jedoch nur um eine Beispiel-Validierungsregel, da ich die "echten" noch nicht ausgearbeitet habe. – Oliver

Antwort

3

Suchst du das?

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" });  
} 

Wenn ja, ich glaube, die erste Version sieht schöner aus.

+0

Danke dafür. Ist die "Ausbeute Pause" notwendig? – Oliver

+0

Nein, ich werde es löschen. –

2

Sicher. Verwenden Sie einfach diese:

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

Danach könnten Sie auch mit Rendite zurück. Sie könnten also Ihr retVal zurückgeben, nachdem Sie die Methode aufgerufen haben, und dann wie in Ihrer ersten Probe fortfahren. Gefällt mir:

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

Die anderen bisher veröffentlichten Lösungen sind gut. Hier ist ein weiterer Weg, um Ihr Problem zu lösen:

  • Erstellen Sie zwei Sequenzen
  • verketten sie
  • die Verkettung Rückkehr.

So:

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" }); 
    ... 
} 
Verwandte Themen