【问题标题】:yield return when appending values on to the end of an existing IEnumerable将值附加到现有 IEnumerable 的末尾时产生返回
【发布时间】:2012-04-11 11:47:30
【问题描述】:

我刚刚发现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 重写它?

【问题讨论】:

  • 请注意,您拼错了“arbitrary”。
  • @EricLippert 哈,确实。我一直拼错这个。在这种情况下,虽然它只是一个示例验证规则,因为我还没有制定出“真正的”规则。

标签: c# yield-return


【解决方案1】:

你在找这个吗?

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

如果是这样,我相信第一个版本看起来更好。

【讨论】:

  • 谢谢。 yield break 有必要吗?
【解决方案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" });
  ...
}

【讨论】:

    【解决方案3】:

    当然。就用这个吧:

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

    【讨论】:

      猜你喜欢
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 2017-06-15
      • 2012-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多