我很惊讶,无论我是在前置还是附加LINQ扩展方法都没关系.
hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
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)
Run Code Online (Sandbox Code Playgroud)我猜想它会更慢,Where
因为它必须找到所有匹配的项目,然后取第一个,前面的FirstOrDefault
可以产生第一个找到的项目.
问:有人可以解释我为什么走错了路吗?
Eri*_*ert 48
我会猜到前缀会更慢,因为它必须找到所有匹配的项目,然后取第一个和前面的FirstOrDefault可以产生第一个找到的项目.有人可以解释为什么我走错了路吗?
你走错了路,因为你的第一个陈述是错误的.Where
是不是需要找到所有匹配的物品之前获取第一个匹配项.Where
"按需"提取匹配项目; 如果你只要求第一个,它只取出第一个.如果你只要求前两个,它只取得前两个.
Jon Skeet在舞台上表现不错.想象一下,你有三个人.第一个人有一张洗牌的牌.第二个人有一件T恤,上面写着"卡片是红色的".第三个人戳了第二个人说"给我第一张牌".第二个人一遍又一遍地戳第一个人,直到第一个人交出一张红牌,然后第二个人交给第三个人.第二个人没有理由继续戳第一个人; 任务完成了!
现在,如果第二个人的T恤上写着"按等级递增排序",那么我们就会有一个非常不同的情况.现在第二个人确实需要从第一个人那里获得每张卡,以便在将第一张卡交给第三人之前找到套牌中的最低牌.
现在,这应该为您提供必要的直觉,以告知订单何时因性能原因而重要."给我红牌然后对它们进行排序"的最终结果与"对所有卡片进行排序然后给我红色"完全相同,但前者要快得多,因为你不必花时间整理你要丢弃的黑卡.
Jam*_*are 11
该Where()
方法使用延迟执行,并将根据请求提供下一个匹配项.也就是说,Where()
不评估并立即返回所有候选对象的序列,它们在迭代时一次提供一个.
由于FirstOrDefault()
在第一个项目之后停止,这将导致Where()
停止迭代.
可以认为FirstOrDefault()
停止执行Where()
就像执行了一样break
.当然,这并不是那么简单,但实质上,因为FirstOrDefault()
一旦找到项目就停止迭代,Where()
不需要继续进行.
当然,这是在应用FirstOrDefault()
on Where()
子句的简单情况下,如果你有其他条款暗示需要考虑所有项目,这可能会产生影响,但在使用Where().FirstOrDefault()' combo or just
FirstOrDefault()'时都是如此谓词.