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

本文关键字:另一个 Enumerable 返回 结果 数据类型 | 更新日期: 2023-09-27 18:24:25

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

考虑到这一点,我想"太棒了!我将返回一个IEnumerable,并使用yield返回每个结果。如果在枚举中使用FirstOrDefault(),则只执行第一个失败的验证,其中将跳过以下内容,除非我们对验证结果enumerable调用ToList()。

我看到的问题是,如果我想把我的验证逻辑分解为多个方法,每个方法都返回一个Enumerable,我必须在那个集合上枚举,并在那里返回另一个yield。(见下面的简化示例)

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

我是否缺少其他关键字,可以从返回相同数据类型的另一个IEnumerable的其他方法中"产生返回集"?有比更简单的语法吗

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

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

不能yield return多个项目。如果你想使用迭代器方法来连接序列,你必须循环它们。

当然,您总是可以完全放弃yield return,并构造您的IEnumerable<T>以使用其他方式返回(LINQ的Concat方法立即出现)。

public IEnumerable<string> Validate(ClassToValidate obj)
{
    var subObjectMessages = ValidateSubObject(obj.OtherObjectToValidate);
    if (string.IsNullOrEmpty(obj.Name))
    {
        return new[] { "empty name" }.Concat(subObjectMessages);
    }
    return subObjectMessages;
}

一旦在函数中引入了yield,就必须继续使用它。目前常用的方法是使用LINQ,它通常更灵活。

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