具有Linq语句性能的Foreach循环

时间:2011-05-03 05:05:43

标签: .net c#-4.0

Witch方法更好,或者更好的方法是什么:

    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号的性能更好。还有更多想法吗?

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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的惰性评估的东西。转换到列表可能实际上是成本你的时间。但是,如果您需要在循环开始之前对进行评估,那么您可能需要这样做,但这并不是一个常见的需求(根据我的经验)。

答案 2 :(得分:0)

第一个通常最适合表现。它会在您循环访问数据时对其进行过滤,因此它不会为列表或数组分配空间来保存所有项目。

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

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

如果比较选项之间的速度,您将看不到太大差异。分配数组并不需要花费太多时间,但稍后会产生很小的影响,因为它们最终必须进行垃圾回收。