我知道LINQ提供的Count()
方法有一個優化,它將檢查源序列是否實施ICollection<T>
,如果是這樣,請調用Count
屬性,而不是迭代整個集合。使用此優化時,底層的IEnumerable<T>
未消耗,因此可以由其他調用Count()
繼續使用。爲什麼從Count()完全使用LINQ Where()方法返回的IEnumerable不是?
值得注意的是,接受謂詞的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
我的期望是伯爵就需要消耗由Where()
返回整個evens
序列和evens.First()
的後續調用會因InvalidOperationException
而失敗,因爲該序列不包含任何元素。
爲什麼這個程序的工作方式呢?在調用Count()之後,我通常不會嘗試使用IEnumerable<T>
。依靠這種行爲會不明智嗎?
大概,這只是有效的,因爲數據的最終來源 - 列表 - 可以迭代多次。 –