【问题标题】:LINQ Enumerable in Enumerable - Why?LINQ Enumerable in Enumerable - 为什么?
【发布时间】:2012-04-01 23:37:19
【问题描述】:

我有一个 Ticket 类,其中包含一个 User 对象列表:

class Ticket {
    public List<User> Users { get; set; }
}

我想获取与工单相关的所有用户。我这样做:

var u = from t in db.Tickets
        where t.Users.Count() > 0
        select t.Users

这可行,但返回一个带有 1 个元素的 Enumerable。该元素是用户的Enumerable

为什么要嵌套?

【问题讨论】:

  • 查看我的帖子,但使用Any() 而不是Count() &gt; 0

标签: c# linq enumerable


【解决方案1】:

首先:LINQ-Query 将始终返回一个可枚举的。

第二:你的 t.Users 是一个 List,它也实现了 IEnumerable。

因此,外部可枚举是 linq 结果集,而内部可枚举是实际的第一个结果,可以转换回用户列表,例如

var u = from t in db.Tickets
       where t.Users.Count() > 0
       select (t.Users as List<User)

【讨论】:

  • 不返回 Enumerable 的 FirstOrDefault() 怎么办?
  • 它返回结果集中的第一个对象(可枚举)或者 - 如果结果集为空 - 一个正确类型的默认对象。
  • 它从 IEnumerable 返回第一个 TSource,而不是具体的 Enumerable 对象。 MSDNmsdn.microsoft.com/en-us/library/bb340482.aspx
  • 然后纠正你的回答,因为它不正确,这就是我所指出的,并非所有 Linq 查询都返回一个 Enumerable!
  • 查询通常总是返回一个可枚举的,但这是一个约定,而不是保证。查询表达式可以是任何类型,包括 void!以这样一种方式实现查询模式是非常不好的做法,即查询的类型不是某种序列,但它肯定是可能的。
【解决方案2】:

你需要做的是

  var u = (from t in db.Tickets from user in t.Users select user).ToList();

然后您将拥有一个扁平化的用户列表。 无需检查 where t.Users.Count() &gt; 0,如果确实需要,您应该使用 where t.Users.Any() 以提高效率。

【讨论】:

  • 请注意,两个froms 转换为SelectMany(),所以这相当于其他一些解决方案。
  • 是的,我知道,谢谢。我应该把两种方式都放在额外的布朗尼点上:-)
  • 根据你的评分,我很确定你知道 :) 这只是给其他读者的一个提示。
  • @Phil:请更正您的语法。 u 被声明了两次。我使用了这个查询:var u = (from t in db.Tickets from user in t.Users select user).ToList();
  • 感谢您发现语法错误。您需要 .ToList() 但如果您使用它,查询将立即被评估,而不是在您迭代结果时被推迟。
【解决方案3】:

SelectMany 方法是您想要的。来自 MSDN 文档:

“将序列的每个元素投影到一个 IEnumerable(Of T) 并将结果序列展平为一个序列。”

因此,您获取所有票证并获取每张票证的所有用户,因此结果列表将是用户列表。您可能还想使用 Distinct 方法来删​​除重复的用户。我假设一个用户可能与不止一张票相关联。

【讨论】:

    【解决方案4】:

    从查询中,我假设您希望所有用户都包含在票证中。

    你可以这样解决:

    List<User> users = new List<User>();
    
    foreach(List<user> u in  db.Tickets.where(ticket => ticktet.Users.Count() > 0).select(ticket => ticket.Users)){
    users.AddAll(u);
    }            
    

    【讨论】:

      【解决方案5】:

      我想你正在寻找

      var u = (from t in db.Tickets
               from u in t.Users
               select u).Distinct();
      

      【讨论】:

        【解决方案6】:

        因为您选择了IEnumerable&lt;Users&gt; 中的List&lt;User&gt;...

        第二个 Enumerable 是你的List&lt;User&gt;

        您可以使用以下查询将其展平。

        db.Tickets.Where(t => t.Users.Any()).SelectMany(t => t.Users)
        

        Any()Count() &gt; 0 快得多,因为它会在第一次出现时停止计算,Count 迭代您拥有的完整用户列表

        【讨论】:

          【解决方案7】:

          您可以像这样将它合并到 IEnumerable: db.Tickets.Where(t => t.Users.Count() > 0).SelectMany(t => t.Users)

          【讨论】:

            【解决方案8】:

            因为它不会将所有 t.Users (t0.Users, t1.Users...) 合并到一个列表中。您需要将它们结合起来。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-11-21
              • 1970-01-01
              • 2013-04-03
              • 2013-08-06
              • 2020-05-18
              • 1970-01-01
              • 2014-01-19
              • 2013-04-01
              相关资源
              最近更新 更多