2010-04-27 61 views
24

奇怪的是,MSDN沒有關於數據結構順序保留屬性的信息。所以我一直在做的前提是:c#順序保存數據結構

  • Hashtable和的Hashset不保留插入順序(也稱爲「哈希」中有贈品)
  • 字典和列表DO保持插入順序。

從此我推斷出,如果我有一個Dictionary<double,double> foo定義曲線,foo.Keys.ToList()和foo.Values.ToList()會給我該曲線的範圍和領域的有序列表沒有搞亂它呢?

回答

32

您不應該期望按任何順序維護常規Dictionary<TKey,TValue>中的密鑰或值。在SortedDictionary<TKey,TValue>中,鍵和值按鍵的值保存 - ,這與插入順序不一樣。

保留插入順序的.NET框架中唯一的內置字典是System.Collections.Specialized.OrderedDictionary。不幸的是,這個類不是通用的 - 但是,寫一個通用的wrapper並不難。請記住,在處理值類型(如intdouble)時,它將導致鍵/值的裝箱(通用字典不會對值類型施加裝箱)。

+1

這是我最初設想的,但是接下來一些Google使用似乎暗示Dictionary DOES保留了插入順序。 OrderedDictionary它是。謝謝! – 2010-04-27 16:36:32

1

As @Anton指出Dictionary<TKey,TValue>是一個無序集合。適當的價值迴歸是巧合,最終會失敗。如果您需要訂購散列表,您應該使用SortedDictionary<TKey,TValue>

+10

'SortedDictionary '不保留插入順序,它基於鍵的自然順序來維護項目。在'System.Collections.Specialized'命名空間中有一個非泛型的'OrderedDictionary'類*,它*以額外的存儲爲代價來保持插入順序。 (它基本上是作爲一個哈希表和一個列表實現的)。 – LBushkin 2010-04-27 16:09:47

-8

通過一切手段,依靠Dictionary<TKey, TValue>來維持秩序!

雖然Dictionary<TKey, TValue>明確指出枚舉排序是未定義的,但我們測試它確實保留了插入排序(至少只要您不從中刪除項目)。如果有人可以提供一個反駁它的測試,我們會非常感興趣,因爲我們的生產代碼依賴於它。

你可能會採取相同的方法,並節省一些努力和你的客戶一些錢。

當然,微軟可能會改變在未來的.NET版本的字典執行,但如果出現這種情況,您的自動化測試會檢測到它,你可以在那個時候用另一個容器代替字典,對嗎?

+13

您正在依靠此功能_in產品代碼_ ???你生氣嗎?詞典確實不會保留插入順序,它在你的情況下確實是一個邊緣情況和你如何使用它的副作用。通過查看反射器中的Insert方法,您可以看到這一點 - 它使用關鍵的哈希代碼來確定將條目放置在後備數組中的位置,然後在「枚舉器」中循環訪問數組。 – thecoop 2010-09-07 14:10:20

+2

@thecoop :我同意依靠時間順序是危險的,但是還有更多的事情會導致'Dictionary'不僅僅是一個邊緣情況。它實際上維護着兩個數組。一個用於存儲實際項目(條目),另一個用於指向前者(桶)的索引。新條目總是添加到條目數組中的下一個可用槽中,而不管散列碼和桶數組發生了什麼。即使你刪除了一個項目,那個入口數組的順序仍然是確定性的(儘管不再是時間)。再次,我永遠不會依賴這個細節。 – 2010-09-07 17:46:05

+2

相信我,我們和你一樣驚訝,但儘可能地嘗試,我們不能寫一個測試來打破我們的產品代碼(無論如何,嘿嘿)。我們還編寫了一個測試,以隨機順序在Dictionary中插入一百萬個項目,迭代它並聲明這些元素以與插入順序相同的順序出現。再次,自動測試會告訴我們,如果由於某種原因,我們將來不能依靠它。 – 2010-09-08 07:24:34