2012-04-20 5 views
1

コレクションに一致するアイテムが1つしかないことがわかっている場合、Linqにこれについて通知する方法はありますか?見つけたら検索を中止するようにしますか?x個のアイテムを見つけた後で、linqクエリを中止しますか?

私はこれらの両方が1つのアイテムを返す前にフルコレクションを検索すると仮定していますか?

var fred = _people.Where((p) => p.Name == "Fred").First(); 
var bill = _people.Where((p) => p.Name == "Bill").Take(1); 

EDIT:人々はFirstOrDefault、またはSingleOrDefaultに執着ようです。これらは私の質問とは関係がありません。コレクションが空の場合は、単にデフォルト値を指定します。私が述べたように、私のコレクションには一致するアイテムが1つあります。

AakashMのコメントは私にとって最も興味深いものです。私は私の仮定が間違っているように見えるだろうが、私はなぜ興味がある。 たとえば、オブジェクトへのlinqが、私のコード例でWhere()関数を実行しているとき、その戻り値にさらに操作があることをどのように知っていますか?

+4

これは、基礎となるプロバイダによって異なりますが、あなたの前提は間違っています。 – AakashM

+1

FirstOrDefaultを使用します。アイテムが見つかると停止し、コレクション内の残りのアイテムは検索しません。そうでなければアイテムが存在しない場合はnullを返します。複数の項目がある場合に例外をスローしたい場合は、SingleOrDefaultを使用しますが、これは選択範囲全体を検索します。 – ThePower

+0

@AakashM:少し質問を編集しました。あなたはまったくコメントできますか? – GazTheDestroyer

答えて

5

あなたの仮定が間違っています。 LINQは遅延実行とlazy evaluationを多く使用します。つまり、Where()に電話をかけたときなど、実際にはコレクションを繰り返すわけではありません。返すオブジェクトを反復処理する場合にのみ、元のコレクションを反復処理します。そしてそれは怠惰なやり方でそれを行います:必要なだけです。

したがって、いずれのクエリもコレクション全体を反復しません。両方とも、最初の要素を見つけた時点まで反復してから停止します。

実際には、2番目のクエリ(Take())でさえ、それを実行しません。結果を反復する場合にのみ、ソースコレクションを反復します。

これはすべてLINQオブジェクトに適用されます。他のプロバイダ(LINQ to SQLなど)は異なる動作をすることができますが、少なくとも遅延実行の原則は通常保持されます。

+0

D'oh!もちろん。私はLINQの延期された実行について読んだが、それについて忘れていた。説明ありがとう。 – GazTheDestroyer

-1

代理人.Where(.SingleorDefault( これは、あなたのための最初のアイテムです。

ただし、指定した番号ではこれを行うことはできません。 2つのアイテムが必要な場合は、コレクション全体を取得する必要があります。

ただし、時間について心配する必要はありません。データベース接続のオープンとクエリの確立には、最も多くの労力が必要です。クエリを実行するにはあまり時間がかからないので、クエリを途中で止める理由はありません:-)

+0

SingleOrDefaultは「最初の」アイテムを見つけられません。 2つのアイテムがある場合、例外がスローされます。あなたはFirstOrDefaultを記述しています – ThePower

+0

私は「最初ANDのみ」と言っています... – Flater

0

私はFirst()はコレクション全体をスキャンしません。最初の試合の後すぐに返されます。しかし、代わりにFirstOrDefault()を使用することをお勧めします。

EDIT:(MSDNから)First()FirstOrDefault()

差:ソースに要素がない場合

First()メソッドは例外をスローします。ソースシーケンスが空のときに代わりにデフォルト値を返すには、FirstOrDefault()メソッドを使用します。

Enumerable.First

関連する問題