【发布时间】:2014-01-24 06:49:39
【问题描述】:
我有一个关于 LINQ 与标准 foreach 循环的效率问题。
我有一个方法,大致如下
var foos = users.Select(this.GenerateNullableFoo).Where(foo => foo != null);
结果出于某种原因,速度非常慢。使用时间戳我能够确定缓慢点恰好在 select 的迭代中(从最终返回语句到下一个方法调用开始的时间)比其他任何东西(总时间
当替换为以下时,整个过程时间减少到每次迭代不到 1 秒。
新代码:
var foos= new List<Foo>();
foreach (var user in users)
{
var foo = GenerateNullableFoo(user);
foo.IfNotNull(f => foos.Add(foo));
}
据我所知,我的代码可以正常工作,并且新代码没有任何问题,但是,我完全不明白为什么使用上面的 Select 比 foreach 看起来慢 10 倍以上过程。是否有任何关于可能导致这种情况的差异的见解?
此外,直到 说 select/foreach 之后,整个 List 才会保存,此时对 db 进行批量调用。
编辑:从起点到终点(和终止)的整个代码块如下:
//Code snippet pictured above
_repo.SaveFoo(Foos);
//at this point, the code terminates and is finished
【问题讨论】:
-
您如何使用您的查询?例如,如果您要多次迭代结果,这很容易解释行为。
-
你试过
var foos = users.Select(this.GenerateNullableFoo).Where(foo => foo != null).ToList();吗?这将创建更类似于foreach的代码。 -
为什么上面有
foo != null,下面有foo.IfNotNull(..)? -
这两个不是等价的。第二个构建一个列表,第一个创建一个 IEnumerable。正如其他 cmets 指出的那样,多次使用第一个结果将导致多次执行。该列表将在后续使用中简单地遍历集合
-
我不确定我的代码将如何多次使用选择的结果。这些 sn-ps 之后的唯一代码是批量保存 _repo.SaveAll(Foos);然后代码完成并完全终止该过程。 @蒂姆。 where 子句作用于生成的 foo 以确保它不为空,这与底部 IfNotNull 子句中所做的相同。这两个项目都只是检查“如果 foo 不为空,则将其保留在列表中/将其添加到列表中”
标签: c# asp.net linq foreach performance