Count()
LINQによって提供されるメソッドには、ソースシーケンスが実装されているかどうかをチェックし、実装されている場合はコレクション全体を反復処理するのではなく、プロパティICollection<T>
を呼び出すという最適化があることを認識していました。Count
この最適化を使用すると、基礎となるIEnumerable<T>
ものは消費されないため、後続の他の呼び出しによって消費される可能性がありますCount()
。
特に、述語を受け入れるCountのオーバーロードは、各要素の値を検査する必要があるため、そのような最適化を実行しません。
次に、次の完全なプログラムについて考えてみます。
using System;
using System.Collections.Generic;
using System.Linq;
namespace count_where_issue
{
class Program
{
static void Main(string[] args)
{
IEnumerable<int> items = new List<int> {1, 2, 3, 4, 5, 6};
IEnumerable<int> evens = items.Where(y => y % 2 == 0);
int count = evens.Count();
int first = evens.First();
Console.WriteLine("count = {0}", count);
Console.WriteLine("first = {0}", first);
}
}
}
印刷する、
count = 3
first = 2
私の予想では、カウントはevens
によって返されたシーケンス全体を消費する必要があり、シーケンスには要素が含まれていないためWhere()
、後続の呼び出しevens.First()
は失敗します。InvalidOperationException
このプログラムがそのように機能するのはなぜですか?IEnumerable<T>
私は通常、次の `Count()の呼び出しを使用しようとはしません。この振る舞いに頼るのは賢明ではないでしょうか?