产生返回另一个相同数据类型的Enumerable的结果

时间:2014-09-25 02:04:36

标签: c# yield-return

我正在编写验证逻辑,我希望调用者只获得他们真正需要的验证消息的数量(有些情况下,只需要第一个验证消息,其他时候,我们现在想要的所有问题都是给定数据)

鉴于此,我想"很棒!我将返回一个IEnumerable,并使用yield返回每个结果。如果在枚举上使用了FirstOrDefault(),则只会执行第一次失败的验证,其中将跳过以下内容,除非我们在验证结果上调用ToList()可枚举。

我所看到的问题是,如果我想将我的验证逻辑分解为多个方法,每个方法都返回一个Enumerable,我必须枚举那个设置,同时还有另一个yield return。 (见下面的简化示例)

public IEnumerable<string> Validate(ClassToValidate obj)
{
  if(string.IsNullOrEmpty(obj.Name)
  {
     yield return "empty name";
  }
  foreach(var message in ValidateSubObject(obj.OtherObjectToValidate))
  {
    yield return message;
  }
}

private IEnumerable<string> ValidateSubObject(OtherClass objToValidate)
{
   yield return ...
}

是否还有其他一些我缺少的关键字,我可以&#34;收益返回设置&#34;从另一个返回另一个相同数据类型的IEnumerable的方法? I.E.是否有比以下更简单的语法:

  foreach(var message in ValidateSubObject(obj.OtherObjectToValidate))
  {
    yield return message;
  }

2 个答案:

答案 0 :(得分:3)

你不能yield return多件物品。如果要使用迭代器方法来连接序列,则必须循环遍历它们。

当然,你总是可以完全放弃yield return并构建你的IEnumerable<T>以使用其他方法返回(LINQ&#39; Concat方法立即浮现在脑海中。)< / p>

public IEnumerable<string> Validate(ClassToValidate obj)
{
    var subObjectMessages = ValidateSubObject(obj.OtherObjectToValidate);

    if (string.IsNullOrEmpty(obj.Name))
    {
        return new[] { "empty name" }.Concat(subObjectMessages);
    }

    return subObjectMessages;
}

答案 1 :(得分:2)

在功能中引入yield后,您必须坚持使用它。目前常见的方法是使用LINQ,它通常更灵活。

public IEnumerable<string> Validate(ClassToValidate obj)
{
  return (String.IsNullOrEmpty(obj.Name) ? new [] { "empty name" } : Enumerable.Empty<string>())
      .Concat(ValidateSubObject(obj.OtherObjectToValidate));
}