yield return при добавлении значений в конец существующего IEnumerable
Я только что узнал о yield return
Я, кажется, очень мило. Я использую его в таком методе:
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
?
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" });
}
Если так, то я считаю, что первая версия выглядит лучше.
Другие решения, опубликованные до сих пор, хороши. Вот еще один способ решить вашу проблему:
- Создать две последовательности
- объединить их
- вернуть конкатенацию.
Так:
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" });
...
}
Конечно. Просто используйте это:
foreach (var item in retVal) {
yield return item;
}
После этого вы также можете продолжить с доходности. Таким образом, вы можете вернуть свой retVal после того, как вызвали метод, а затем продолжить, как в первом примере. Как это:
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" });
//...
}