【问题标题】:Logical difference between LINQ Where() and FirstOrDefault()LINQ Where() 和 FirstOrDefault() 之间的逻辑区别
【发布时间】:2013-11-18 15:36:42
【问题描述】:

我知道这听起来可能是一个重复的问题(例如 thisthis ),但我想弄清楚此查询中将发生的数字迭代。

我的假设如下:

假设我收集了 1000 件物品。

  1. 在 Where() 查询中,它遍历每个项目并将其添加到 IEnumerable。即它总是需要 O(n)。

    foreach (var item in myList)
    {
        if(//<condition>)
        {
            //add it to list/enumerable
        }
        //continue through entire list
    }
    
  2. FirstOrDefault(&lt;condition&gt;) 查询中,它开始遍历集合,并在获得与&lt;condition&gt; 匹配的项目并返回单个元素或仅当没有项目与&lt;condition&gt; 匹配时才返回循环将遍历整个列表。

所以复杂度可以从 O(1) 到 O(n)

foreach (var item in myList)
{
    if(//<condition>)
    {
        //return item
        break;
    }
}

如果这是正确的,那么最好使用 FirstORDefault 进行单件退货。?

【问题讨论】:

  • Big-O 表示为最坏的情况。 FirstOrDefault() 将是 0(n)。
  • 对于单件退货,您应该使用FirstOrDefault(或类似的方法,例如Single),而不是Where,因为这是它最好的表达方式。它是否比其他实现更快是另一个问题。

标签: c# linq


【解决方案1】:

Where 实际上是延迟的 - 即在枚举发生之前它没有任何成本。

Where 看起来有点像这样,并返回一个新的IEnumerable&lt;T&gt;

foreach (var item in enumerable)
{
    if (condition)
    {
        yield return item;
    }
}

FirstOrDefault 返回T

【讨论】:

  • 哇。我不知道这个延迟的事情。感谢您消除疑虑。
  • @deathrace 当您看到标准 linq 操作返回 IEnumerable&lt;T&gt;(或其派生形式之一)时,它是延迟结果。
  • @DanielA.White 如果我们正在处理 IQueryable,有什么更好的方法,我认为 Where() 将是一个不错的选择,因为它将在数据源上应用过滤器。对吗?
  • @Ummar 它取决于查询提供者。
  • @DanielA.White 我正在使用 LINQ to SQL。对它的内部工作有任何想法吗?
【解决方案2】:

FirstOrDefault 将在/如果发现任何内容时停止检查(即中断)。

编辑: 但是,正如 Daniel 指出的那样,Where 是延迟的,因此您也可以自己停止迭代,它将具有与 FirstOrDefault 相同的性能(尽管那时您不妨只使用 FirstOrDefault)

【讨论】:

  • 问题的关键是OP认为Where()会在传递给FirstOrDefault之前完全枚举列表。这意味着他的假设是不正确的,不正确的。
【解决方案3】:

FirstOrDefault 枚举查询,而Where 只返回一个新的枚举器。下面的语句给出了相同的结果:

var result = coll.FirstOrDefault(predicate);
var result = coll.Where(predicate).FirstOrDefault();

【讨论】:

  • 如果我想找到结果,那么哪个更好?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
  • 2019-06-08
  • 2016-07-03
相关资源
最近更新 更多