2012-05-02 76 views
32

我有一個關於訂單IEnumerable(或IEnumerable<T>,無所謂)的問題。IEnumerable和訂單

我們知道,通過IEnumerable的迭代是僞代碼可以通過以下方式書寫:

while (enumerable.HasNext()) 
{ 
    object obj = enumerable.Current; 
    ... 
} 

現在,假設,一個需要在分類收集操作。在這種情況下可以使用IEnumerable還是使用支持索引的其他方法(即IList)更好?

換句話說:IEnumerable的合同是否對訂單作出一般保證?

UPD:因此,IEnumerable不適用於保證排序的通用接口。新的問題是什麼接口或類應該用於訂單不可變集合? ReadonlyCollectionIList?他們都包含Add()方法(甚至沒有在前者實施)。有什麼建議?

P.S我自己的想法:IEnumerable不提供任何有關訂購的保證。正確的實現可以在不同枚舉中以不同順序返回相同的元素(考慮SQL查詢)

P.P.S.我知道LINQ First(),但如果IEnumerable沒有說它的排序的話,這個擴展是相當無用的。

回答

25

IEnumerable/IEnumerable<T>對訂購不作任何保證,但使用IEnumerable/IEnumerable<T>的實現可能會也可能不會保證排序。

舉例來說,如果你列舉List<T>,爲了得到保證,但如果你列舉HashSet<T>沒有提供這樣的保證,但都將使用IEnumerable<T>接口枚舉。

+1

另一個例子是'Dictionary <,>'。它清楚地記錄了它的條目枚舉的順序是未定義的。因此,像'dict.Last().Key'這樣的代碼(其中'dict'是'Dictionary <,>'而'Last()'是LINQ擴展方法)是沒有意義的。 (我聽說有一位開發人員正在做這件事。) –

+1

我想補充說,它對於正確理解什麼是對某些通用集合訂單的保證很重要。所以順序保證不是關於特定的順序(比如說,作爲排序的結果),而是關於保證相同集合的元素的順序對於隨後的枚舉是相同的。大多數收集不明確保證。 IList 只代表一種字典,其中鍵是索引。 –

+0

IOrderedEnumerable可能是一個標誌,認爲集合保證了順序(雖然接口仍然沒有),但它比我們需要的更多 - 它通常代表一個特定的SORT順序,而我們需要任何(隨機)順序,這只是在枚舉之間保證。總之,只有具體的實現才能真正保證順序(例如Array,List )。 –

12

實現細節。 IEnumerable將枚舉該項目 - 如何實施取決於實施。 MOST列表等按照它們的自然順序(索引0向上等)運行。

IEnumerable的合同是否保證我們在一般情況下有一定的順序?

不,它只保證列舉(每個項目一次等)。 IEnumerable沒有保證順序,因爲它也可用於無序項目。

我知道LINQ First(),但是如果IEnumerable沒有對它的順序說一個字,這個擴展就沒用了。

不,它不是,因爲你可能有內在的秩序。您以SQL爲例 - 結果是一個IEnumerable,但如果我之前強制排序(通過使用OrderBy()),那麼IEnumerable將按照LINQ的定義進行排序。 AsEnumerable()。First()通過Order獲取我的第一個項目。

4

你可以混合兩點:枚舉和排序。

當你枚舉IEnumerable時,你不應該關心順序。你使用這個接口,它的實現應該關心順序。

例如:

void Enumerate(IEnumerable sequence) 
{ 
    // loop 
} 

SortedList<T> sortedList = ... 
Enumerate (sortedList); 

裏面,它仍然有固定的順序列表,但方法不知道具體的接口實現的,它的特點的方法。

6

也許您正在尋找IOrderedEnumerable界面?它由OrderBy()等擴展方法返回,並允許隨後使用ThenBy()進行排序。

+0

不幸的是,如果你想接受像IList這樣的接口來保證一個訂單,但是不會從IOrderedEnumerable繼承,那麼這將不起作用。請參閱http://stackoverflow.com/q/5429974/1157054 – Ajedi32