2011-05-03 44 views
0

女巫的做法是更好的,或什么是这样做的更好的办法:Foreach循环使用LINQ语句的性能

Stuffs[] stuffs = getStuffs(); 
    1) 

    foreach (var stuff in stuffs.Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue)) 
    { 
    } 

    2) 
    foreach (var stuff in stuffs.Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue).ToList()) 
    { 
    } 

    3) 
    stuffs = stuffs.Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue).ToArray(); 
    foreach (var stuff in stuffs) 
    { 

    } 

我觉得数字3是获得更好的性能。还有什么想法?

回答

2

一般:措施!

出于可读性我说的1的混合和3.该长在foreach代码变得有点不可读的头部直接一条线,所以我把该查询在上面的单独的行循环:

var stuffs = from x in getStuffs() 
      where x.StartDate <= DateTime.Now.AddDays(-1) && 
        x.EndDate != DateTime.MinValue 
      select x; 

var stuffs = getStuffs().Where(x => x.StartDate <= DateTime.Now.AddDays(-1) && x.EndDate != DateTime.MinValue); 

但是你的愿望。但在那之后,使用普通的foreach循环:

foreach (var s in stuffs) { 
} 

也没有必要转换成一个列表,因为foreach可以遍历可迭代的集合,包括LINQ的懒惰评价的东西。转换到列表可能实际上费用你的时间。如果您需要在之前评估循环,但您可能需要这样做,但这并不是一个普遍的需求(以我的经验)。

+0

感谢您的解释 – 2011-05-03 06:22:11

2

你应该检查,但通常获取的数据和你在循环中执行的操作不仅仅是迭代。第一个应该更快,因为你没有创建一个新的列表,你不需要在这里。
我也建议将DateTime.Now.AddDays(-1)置于一个变量中 - 除了possible speed benefits之外,它的值在迭代期间可能会改变,这可能会影响程序的正确性。

+0

对'DateTime.Now'事物的良好调用。 – Joey 2011-05-03 05:14:24

0

第一个通常是最好的表现。它将在您循环时过滤数据,因此它不会为列表或数组分配空间来容纳所有项目。

第二和第三个表现几乎相同。它们都过滤数据并将结果放入数组,并在需要时通过复制到新数组来生长数组。

第三种方法也用过滤数据数组替换原始数据,如果稍后使用数据,这将是相关的。另外,这样做会释放原始数据,以便在需要时可以进行垃圾回收,这对于源数组非常庞大的特殊情况下的性能可能会更好,并且如果您在代码中使用了大量内存在循环内。

如果比较选项之间的速度,则不会看到太多差异。分配数组并不需要太多时间,但稍后它将产生一个小的影响,因为它们必须最终被垃圾收集。