2012-06-30 36 views
1

我知道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>。依靠這種行爲會不明智嗎?

回答

1

這是IEnumerator<T>你將無法使用。但是,Count和First各自創建一個單獨的枚舉器(通過調用上的GetEnumerator)。

+1

大概,這只是有效的,因爲數據的最終來源 - 列表 - 可以迭代多次。 –

1

無論什麼給你的印象是Count()以任何方式影響原始IEnumerable?

的文檔不提這種事......

http://msdn.microsoft.com/en-us/library/bb338038.aspx

+0

我從LINQ的運作閱讀喬恩斯基特的博客文章得到的印象 - 尤其是這篇文章:http://msmvps.com/blogs/jon_skeet/archive/2010/12/26/reimplementing-linq-to-objects-part-7-count-and-longcount.aspx –

+0

Skeet是這麼說的嗎?哦...文檔必須是錯的;) – demoncodemonkey

2

我不知道這是不是你的意思,但evens.Count()evens.First()都列舉了items.Where(...)

您可以在以下的輸出看到這一點:

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 => isEven(y)); 

     int count = evens.Count(); 
     Console.WriteLine("count = {0}", count); 

     int first = evens.First(); 
     Console.WriteLine("first = {0}", first); 

    } 

    private static bool isEven(int y) 
    { 
     Console.Write(y + ": "); 

     bool result = y % 2 == 0; 

     Console.WriteLine(result);  
     return result; 
    } 
} 

那就是:

1: False 
2: True 
3: False 
4: True 
5: False 
6: True 
count = 3 
1: False 
2: True 
first = 2 
相關問題