2012-03-05 54 views
2

我試圖取代T[]List<T>用途爲函數的參數和更適當的類型,如IEnumerable<T>ICollection<T>IList<T>返回值。的ICollection <T>是基於非索引,但TakeWhile()存在

ICollection<T>從我的理解是可取的IList<T>您只需要基本/簡單的收集功能(例如枚舉和計數功能),因爲它提供了最小的限制。從這裏閱讀我認爲的主要差異之一ICollection<T>並不要求底層集合是基於索引的,其中IList<T>在做什麼?

在了我需要更換List<T>.GetRange()電話,我很驚訝地發現其中有一個重載支持基於索引選擇ICollection<T>.TakeWhile()擴展方法切換我List<T>引用? (msdn link)

我很困惑爲什麼這個方法存在於ICollection中,這裏沒有任何索引基於這個接口?我誤解了,或者如果這個方法實際上工作,如果底層集合是例如一個Hashset或什麼的?

回答

2

與大多數LINQ一樣,該方法在IEnumerable<T>上。只有將索引器傳遞給消費者(如TakeWhile)的任何功能只需在循環遞增計數器時循環。某些API可能會使用索引器優化優化,然後由他們決定是否執行該操作,或者僅使用IEnumerable<T>並簡單地跳過(等)不需要的數據。

例如:

int i = 0; 
foreach(var item in source) { 
    if(!predicate(i++, item)) break; 
    yield return item; 
} 
2

索引可以在不收集的支持它

int i = -1; 

foreach(var item in collection) 
{ 
    i++; 
    // item is at index i; 
} 
0

TakeWhileSystem.Linq.Enumerable類工作的其他擴展方法對所有類型的實施IEnumerable<T>來完成。它們都在迭代集合(使用foreach語句)並執行適當的操作。

這裏是TakeWhile方法的實現,有一些簡化:

private static IEnumerable<TSource> TakeWhile<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    foreach (TSource item in source) 
    { 
     if (!predicate(item)) 
     { 
      break; 
     } 
     yield return item; 
    } 
} 

正如你看到的,它只是在收集迭代,並計算謂詞。幾乎所有其他LINQ方法都是如此。當您使用任何其他收集品時也會發生同樣的情況,如HashSet<T>

相關問題