2009-09-04 63 views
2

我一直在阅读关于使用LINQ而不是使用每个循环的性能的公平性,并且从我理解的使用LINQ查询会稍微慢一点,但通常为了方便和表现力而值得。然而,如果你在for循环中使用查询的结果,我感到有点困惑。我应该使用LINQ进行此查询吗?

假设我有一个名为'Locations'的集合和一个名为'Items'的对象集合。每个“项目”只能属于一个“地点”。我想链接相同位置下的项目。如果我要做到这一点使用正常“对于每个”循环将是这样的:

For Each it as Item in Items 
    If it.Location.equals(Me.Location) 
     Me.LinkedItems.Add(it) 
    End If 
Next 

但是如果我是使用LINQ它反而会是这样的:

For Each it as Item in Items.Where(Function(i) i.Location.equals(Me.Location)) 
    Me.LinkedItems.Add(it) 
Next 

现在我的问题是,第二个(LINQ)选项是否会遍历整个'Items'集以完成查询,然后循环遍历结果以将它们添加到列表中,导致基本上是两个循环,或者它会执行一个循环循环像第一个(For Each)选项?如果答案是前者,那么我认为在这种情况下使用LINQ会很愚蠢。

回答

8

它会做一个循环 - 这是懒惰的评估。

但是,您可能可以做得比这更好。什么是LinkedItems的类型?如果有合适的AddRange方法,你应该能够做到:

Me.LinkedItems.AddRange(Items.Where(Function(i) i.Location.equals(Me.Location))) 

更多关于懒惰的评价

基本上Where保持一个迭代器,只有找到下一个匹配的项目,当你去问问。在C#中,执行将是这样的:

// Error handling omitted 
public static IEnumerable<T> Where(this IEnumerable<T> source, 
            Func<T, bool> predicate) 
{ 
    foreach (T element in source) 
    { 
     if (predicate(element)) 
     { 
      yield return element; 
     } 
    } 
} 

这是使用yield return这里这将使它懒洋洋地评估。如果你不熟悉C#迭代器块,你可能想看看thesearticles,这些更详细地解释它们。

当然Where中可以已经被“手动”实现,以代替使用迭代器块的,但上述实施足以显示懒惰评估。

+0

不公平!我首先发现它! ;) – RCIX 2009-09-04 06:27:46

+0

太棒了,正是我在寻找的感谢! – link664 2009-09-04 06:31:43

3

它将执行一次查询,因为您正在对Items.Where列表进行推理。在你的情况下,这是一个预先筛选的条件列表,你应该真的去与LINQ。

+0

+1比Skeet快。 – MarkJ 2009-09-05 09:17:01