我应该使用LINQ进行此查询吗?

时间:2009-09-04 06:22:29

标签: vb.net linq optimization

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

假设我有一个名为'Locations'的集合和一组名为'Items'的对象。每个“项目”只能属于一个“位置”。我想将相同位置下的项链接到彼此。如果我使用正常的'For Each'循环来执行此操作,它将是这样的:

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会很愚蠢。

2 个答案:

答案 0 :(得分: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#迭代器块,可能需要查看these articles,它们会更详细地解释它们。

当然Where 可以实现“手动”而不是使用迭代器块,但上面的实现足以显示延迟评估。

答案 1 :(得分:3)

它将执行一次查询,因为您正在预订Items.Where列表。在你的情况下,这是你想要的条件的预过滤列表,你应该真的使用LINQ。