Reputation: 11617
I just found out about yield return
, I seems really nice. I use it in a method like this:
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.
}
However, I need to change this method to return some ValidationResults from a child method. Without using yield
, the code would look like this:
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;
}
Is it possible to rewrite this using yield
?
Upvotes: 6
Views: 4443
Reputation: 660387
The other solutions posted so far are good. Here's another way to solve your problem:
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" });
...
}
Upvotes: 3
Reputation: 15673
Are you looking for this?
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" });
}
If so, I believe the first version looks nicer.
Upvotes: 4
Reputation: 39630
Sure. Just use this:
foreach (var item in retVal) {
yield return item;
}
After that, you could also continue with yield returns. So you could return your retVal after you called the method and then continue as in your first sample. Like this:
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" });
//...
}
Upvotes: 2