2015-10-04 10 views
13

私は奇妙な問題に直面しています。ここで私は問題を再現しました。IEnumerableが機能を繰り返す

Random r = new Random(); 
List<int> x = new List<int> {1, 2, 3, 4, 5, 6}; 

var e = x.OrderBy(i => r.Next()); 
var list1 = e.ToList(); 
var list2 = e.ToList(); 

bool b = list1.SequenceEqual(list2); 
Console.WriteLine(b); // prints false 

これまで、Linq関数は呼び出されたときに実行されると考えました。しかし、この方法では、ToListというLinq関数OrderByをもう一度呼び出すと思われます。どうしてこんなことに?

+5

[クエリの実行](https://msdn.microsoft.com/en-us/library/vstudio/bb738633(v=vs.100).aspx)を参照してください。「LINQクエリは、クエリ変数がクエリ変数が作成されたときではなく、繰り返されます。これは遅延実行と呼ばれます。 –

+0

@Idle_Mind *遅延実行のドキュメントであることを追加する必要があります。*すべてのLINQメソッドが繰り返し実行されるわけではありません。 –

答えて

19

あなたは遅延実行を見ています。 LINQクエリを作成するときは、基本的には「要求されたときにこれらの手順を実行してデータソースを操作する」という青写真です。ここでのトリッキーな部分は、この要求がLINQ操作の個別のセットによってのみ行われることです(.ToList()はこれらのいずれかです)。

e.ToList()を呼び出すと、データソースがランダム化されます。その理由は、青写真が行うべきことだからです。この同じ青写真でもう一度.ToList()に電話をかけたら、最初からやり直してもう一度ランダム化します。

青写真には状態が含まれていないので、途中で何をすべきかだけを示しています。

+5

正確には、LINQは可能な場合は遅延実行を使用します。 'OrderBy'または' Where'に対しては、要求されたとき(すなわち 'ToList'への呼び出しによって)だけ評価されます。 'Count'や' Sum'のような他のものに対しては、すぐに実行されます。 –

+1

@DanielRose基本的に、可能な限り、LINQは遅延実行を使用します。たとえば、コレクション全体を反復することなく、カウントまたは合計することができます。 –

+3

@YuvalItzchakovコレクション全体を反復することなく、数えたり合計したりすることはできません。それはあなたが意味していたものですよね? – Martijn

関連する問題