【问题标题】:C# Linq Where(expression).FirstorDefault() vs .FirstOrDefault(expression)C# Linq Where(expression).FirstorDefault() 与 .FirstOrDefault(expression)
【发布时间】:2011-11-09 01:15:31
【问题描述】:

这两个Linq查询有什么区别:

var result = ResultLists().Where( c=> c.code == "abc").FirstOrDefault();
// vs.
var result = ResultLists().FirstOrDefault( c => c.code == "abc");
  • 语义是否完全相同?
  • 如果语义相等,predicate form of FirstOrDefault 是否比Where() 加上普通的FirstOrDefault() 提供任何理论上或实际的性能优势?

【问题讨论】:

  • 为了代码简洁使用第二个..
  • @nawfal - 为了简洁,我会说使用第一个。

标签: c# linq


【解决方案1】:

两者都可以。

它们都懒惰地运行 - 如果源列表有一百万个项目,但第十个项目匹配,那么两者都只会从源中迭代 10 个项目。

性能应该几乎相同,任何差异都完全无关紧要。

【讨论】:

  • 没有区别微不足道 - 每天 500 名用户调用 1000 个项目,1 毫秒加起来很长。
  • @NewAmbition - 你说的一天不到百分之一。这不是很多时间。当我比较这两种方法时,我得到的差异是超过 150,000 个项目的计算结果为 1ms(不是每个项目为 1ms,所有 150,000 个项目为 1ms)。因此,基于您的 500 x 1,000 项查询,每天大约需要 0.003 毫秒。这并不重要。
  • 我以为这个词会是斜体,而不是粗体:|你是对的,虽然我用的是一个臃肿的例子。我不打算听起来很混蛋,只是有时微小的性能命中会加起来:)
  • 我的代码编辑器检测到 Where(X)+First() 并建议改为使用 First(X)。
  • 0.003ms - 我想你想写 3ms。 “一天的百分之一”是一个非常糟糕的指标。如果您每天 8 小时有 100 次随机延迟约 3 秒,那么只有 1% 的时间,但您想在一天结束时将计算机扔出窗外。
【解决方案2】:

第二个。在所有其他条件相同的情况下,第二种情况下的迭代器可以在找到匹配项后立即停止,第一个迭代器必须找到所有匹配项,然后选择其中的第一个。

【讨论】:

  • 我相信Where 会导致“投影”或“惰性可枚举序列”(虽然可能会有更多的开销,但它不需要运行来自ResultList 的更多元素,见尾注),但在大多数情况下我选择后者....对于 LINQ2SQL 或类似的情况,我不知道查询生成器会做什么。
  • 不正确 - LINQ 的链接行为意味着它会延迟迭代。对于这两种方法,如果第一项是匹配项,则它们不会再进一步​​。
  • @Enigmativity:并非所有 Linq 提供程序都如此。虽然 Linq to Objects 确实如此,但基于 SQL 基础的提供程序必须在返回第一个对象之前返回(或至少处理)整个集合。底线是,无论某些提供者提供什么样的底层优化,因为你不能依赖它在所有情况下都是正确的,所以最好选择在概念上总是给出正确行为的东西,所有其他条件都相同。跨度>
  • @DaveC - 你会期望最基本的提供者能够确定FirstOrDefault 应该返回TOP 1 项目,确定吗?
  • 我开始收到“等待操作超时”。在大型数据集上使用Where(query).FirstOrDefault()。当我将其更改为FirstOrDefault(query) 时,我不再看到它;所以也许这个答案有些东西。无论如何,代码读起来稍微好一些。
【解决方案3】:

很好的讨论,以上所有答案都是正确的。

我没有进行任何性能测试,但根据我的经验,FirstOrDefault() 有时比 Where().FirstOrDefault() 更快且优化。

我最近修复了内存溢出/性能问题(“神经网络算法”)并修复了将 Where(x->...).FirstOrDefault() 更改为简单的 FirstOrDefault(x->..)。

我忽略了编辑将 Where(x->...).FirstOrDefault() 更改为简单的 FirstOrDefault(x->..) 的建议。

所以我相信上述问题的正确答案是

第二个选项是所有情况下的最佳方法

【讨论】:

    【解决方案4】:

    Where 实际上是延迟执行 - 这意味着,表达式的计算被延迟到实际需要其实现的值。它通过避免不必要的执行大大提高了性能。

    Where 看起来有点像这样,并返回一个新的 IEnumerable

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

    FirstOrDefault() 返回<T> 并且不抛出任何异常或在没有结果时返回null

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      • 1970-01-01
      • 2012-06-15
      • 1970-01-01
      相关资源
      最近更新 更多