【问题标题】:Yield return results of another Enumerable of the same datatype产生相同数据类型的另一个 Enumerable 的返回结果
【发布时间】:2014-11-19 16:20:01
【问题描述】:

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

鉴于此,我想“太棒了!我将返回一个 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 ...
}

我是否缺少其他一些关键字,我可以从返回相同数据类型的另一个 IEnumerable 的其他方法“产生返回集”? IE。有没有比以下更简单的语法:

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

【问题讨论】:

    标签: c# yield-return


    【解决方案1】:

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

    当然,您始终可以完全删除 yield return 并构造您的 IEnumerable&lt;T&gt; 以使用其他方式返回(立即想到 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;
    }
    

    【讨论】:

    • linq 的 Concat 操作是否会遍历枚举?我希望避免实际执行所有代码(例如,如果可能,我希望避免调用一些验证步骤。
    • @NathanTregillus, Concat 创建一个懒惰的IEnumerable,它从第一个集合产生(逐项),然后是第二个当它被迭代时,所以你保留问题中描述的确切行为。
    • 谢谢基里尔!这有助于我了解幕后发生的事情!
    【解决方案2】:

    一旦你在一个函数中引入了yield,你就必须坚持下去。如今,一种常见的方法是使用 LINQ,它通常更灵活。

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

    【讨论】:

    • 感谢丹的帮助!很高兴所有有用的答案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 2018-03-28
    • 1970-01-01
    相关资源
    最近更新 更多