2009-09-04 12 views
2

私はLINQを使うのではなく、LINQを使うのではなく、LINQクエリを使って理解できることは少し遅くなりますが、便宜と表現力のためにはそれほど価値があると思います。しかし、私は、あなたがforループでクエリの結果を使用する場合、どれだけ遅いかについて少し混乱しています。このクエリにLINQを使用する必要がありますか?

「Locations」というセットと「Items」というオブジェクトのセットがあります。それぞれの「アイテム」は1つの「場所」にしか属しません。私は同じ場所の下にあるアイテムをお互いにリンクしたい。

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

今私:私はLINQを使用していた場合、それは代わりに、これだろうしかし

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

:私はループ「は、それぞれについて」通常を使用してこれを実行した場合には、このようなものになるだろう質問は、2番目の(LINQ)オプションがクエリを完了するために 'Items'セット全体を1回ループし、結果をループしてリストに追加して、実質的に2つのループになるか、最初の(For Each)オプションのようにループしますか?答えが前者なら、私はこの状況でLINQを使うのは愚かであると仮定します。

答えて

8

これは1つのループを行います。これは怠惰に評価されます。

ただし、これよりも優れている可能性があります。 LinkedItemsのタイプは何ですか?それは適切なAddRangeメソッドを持っている場合は、あなたが行うことができるはず:

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

遅延評価の詳細

基本的にWhereはイテレータを維持し、ときにのみ、次の一致する項目を検索しますそれを求めます。それはそれは遅延評価になるだろう、ここyield returnの使用だ

// 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; 
     } 
    } 
} 

:C#では、実装が何かのようになります。 C#イテレータブロックに慣れていない場合は、these を詳しく見てください。

もちろん、Whereはイテレータブロックを使用する代わりに "手動で"実装されていますが、上記の実装では遅延評価を表示するのに十分です。

+0

フェアー!私はそれを最初に見つけた! ;) – RCIX

+0

素晴らしい、まさに私が感謝のために探していたもの! – link664

3

これは、Items.Whereのリストを推測しているため、一度クエリを実行します。あなたのケースでは、それはあなたが望む条件の事前フィルタリングされたリストであり、あなたは本当にLINQに行くべきです。

+0

+1はSkeetよりも高速です。 – MarkJ

関連する問題