c# - LINQ 扩展方法的顺序不影响性能?

标签 c# .net linq

令我惊讶的是,我是否预先添加或附加 LINQ 扩展方法显然无关紧要。

使用 Enumerable.FirstOrDefault 测试:

  1. hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
  2. hugeList.FirstOrDefault(x => x.Text.Contains("10000"));

    var hugeList = Enumerable.Range(1, 50000000)
        .Select(i => new { ID = i, Text = "Item" + i });
    
    var sw1 = new System.Diagnostics.Stopwatch();
    var sw2 = new System.Diagnostics.Stopwatch();
    
    sw1.Start();
    for(int i=0;i<1000;i++)
        hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
    sw1.Stop();
    
    sw2.Start();
    for(int i=0;i<1000;i++)
        hugeList.FirstOrDefault(x => x.Text.Contains("10000"));
    sw2.Stop();
    
    var result1 = String.Format("FirstOrDefault after: {0} FirstOrDefault before: {1}", sw1.Elapsed,  sw2.Elapsed);
    //result1: FirstOrDefault after: 00:00:03.3169683 FirstOrDefault before: 00:00:03.0463219
    
    sw2.Restart();
    for (int i = 0; i < 1000; i++)
        hugeList.FirstOrDefault(x => x.Text.Contains("10000"));
    sw2.Stop();
    
    sw1.Restart();
    for (int i = 0; i < 1000; i++)
        hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
    sw1.Stop();
    
    var result2 = String.Format("FirstOrDefault before: {0} FirstOrDefault after: {1}", sw2.Elapsed, sw1.Elapsed);
    //result2: FirstOrDefault before: 00:00:03.6833079 FirstOrDefault after: 00:00:03.1675611
    
    //average after:3.2422647 before: 3.3648149 (all seconds)
    

我猜想在 Where 前面添加会比较慢,因为它必须找到所有匹配项,然后取第一个,而前面的 FirstOrDefault 可能会产生第一个找到的元素。

问:有人可以解释为什么我在错误的轨道上吗?

最佳答案

I would have guessed that it would be slower to prepend Where since it must find all matching items and then take the first and a preceded FirstOrDefault could yield the first found item. Can somebody explain why i'm on the wrong track?

您走错了路,因为您的第一个陈述根本不正确。 哪里 不需要在获取第一个匹配项目之前找到所有匹配项目。 Where “按需”获取匹配项;如果你只要求第一个,它只会获取第一个。如果您只要求前两个,它只会获取前两个。

Jon Skeet 在舞台上表现出色。假设你有三个人。第一个人拿着一副洗好的牌。第二个人有一件 T 恤,上面写着“where card is red”。第三个人戳第二个人说“给我第一张牌”。第二个人一遍又一遍地戳第一个人,直到第一个人递出一张红牌,第二个人随后将红牌递给第三个人。第二个人没有理由继续戳第一个人;任务完成!

现在,如果第二个人的 T 恤上写着“按等级升序排序”,那么我们的情况就完全不同了。现在第二个人确实需要从第一个人那里拿到每张牌,以便在将第一张牌交给第三个人之前找到牌组中最低的一张牌。

现在这应该会给您必要的直觉来判断顺序何时对性能有影响。 “给我红牌然后排序”的最终结果与“排序所有牌然后给我红牌”完全相同,但是前者要快得多,因为你不必花任何时间来排序您要丢弃的黑色卡片。

关于c# - LINQ 扩展方法的顺序不影响性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10110013/

相关文章:

c# - .net 网页浏览器控件

c# - 在序列化时调用 GetObjectData

c# - 合并 IEnumerable 中的重复元素

c# - 分组查询 Linq

c# - 窗体关闭但可见

c# - 并非所有属性都在 WCF 调用中发送或接收

c# - iTextSharp - 如何设置不可见的签名字段名称

c# - 尝试将第三张工作表添加到电子表格时,为什么会出现 "Invalid index"?

c# - 线程结束后执行一条语句

c# - String[] 中的部分匹配