2012-10-16 20 views
0

我最近找到了包含.NET的排序在內的高效代碼Dictionary<string,CustomObject>。基本上是將字典複製到臨時表中,然後.Clear()原始代碼,並通過Linq表達式,通過CustomObjects中的DateTime值插入KeyValuePairs。對.NET Dictionary進行排序 - 錯誤或不受支持的功能?

我希望這段代碼不能正常工作,並且已經刪除它,期望字典(以及HashSet)不能被排序。然後我寫了下面的測試代碼,當我使用foreach循環進行迭代時,我驚訝地顯示了字典中的一個排序輸出。

這是在當前實現Dictionary<TKey, TValue>中的隨機效應,它可能在當前情況下工作,但在另一個.NET實現中失敗?或者它是在.NET Dictionaries中使用的標準功能?

我仍然認爲生產代碼有問題,但工作。我是否應該刪除它,需要長時間的測試,如果訂單在我發現分類程序的地方以外的其他地方使用,還是安全地保留原樣?

這裏是我的測試代碼:

static void Main(string[] args) 
{ 
    var rnd = new Random(); 
    var dict = new Dictionary<int, string>(); 
    for (int i = 0 ; i < 10 ; i++) 
    { 
     int rndValue; 
     do 
     { 
      rndValue = rnd.Next(100); 
     } 
     while (dict.ContainsKey(rndValue)); 

     dict.Add(rndValue, "MyValue#" + i); 
    } 

    foreach (KeyValuePair<int, string> pair in dict) 
    { 
     Console.WriteLine("Key: " + pair.Key + ", Value: " + pair.Value); 
    } 

    Console.Write("Enter..."); 
    Console.ReadLine(); 

    var dictBuff = dict.ToDictionary(p => p.Key, p => p.Value); 
    dict.Clear(); 

    var sortdict = from pair in dictBuff orderby pair.Key ascending select pair; 

    foreach (KeyValuePair<int, string> pair in sortdict) 
    { 
     dict.Add(pair.Key, pair.Value); 
    } 

    Console.WriteLine("'Sorted' Dictionary:"); 

    foreach (KeyValuePair<int, string> pair in dict) 
    { 
     Console.WriteLine("Key: " + pair.Key + ", Value: " + pair.Value); 
    } 

    Console.Write("Enter..."); 
    Console.ReadLine(); 

} 

回答

5

它是基於當前實現,但在不同的實現不能保證。除非您使用SortedDictionary,或者如果您更改最後一個foreach循環以遍歷dict.OrderBy(pair => pair.Key),否則不保證該順序。

From the documentation (Remarks section)

對於枚舉的目的,字典中的每個項被視爲表示值及其鍵中KeyValuePair結構。 項目返回的順序未定義。

+0

他看到的行爲不是隨機效應。這是Dictionary當前內部實現的一個副作用。你真的會把它們放回原來的順序。它不應該被計算在內,因爲Dictionary的實現可能會改變。 – hatchet

+0

@hatchet:是的。更新爲清晰。 –

+0

@hatchet:我希望MS會指定一個沒有任何項目被刪除的'Dictionary'將會按照它們添加的順序返回所有項目。對於因刪除而騰空的插槽是否或何時得到回收將作出任何保證將增加字典的成本,但從未從中刪除東西的字典形成一個常見的使用案例,並且無需提供更強的保證(非常通用的HashTable如何在不刪除任何項目的情況下便宜地保證單作者多讀者線程安全) – supercat

1

辭典是簡單地爲每個元素的標識符的列表,因此元件將在它們已被放置在該命令被返回。但是,沒有保證沒有人例如刪除一個元件僅再次插入它,這將把它放在後面。

如果您想確保字典保持排序,我建議您使用SortedDictionary類。

或者,您可以讓LINQ按照您的需要對字典進行排序。

順便說一句,你可以更換該部分代碼:

var sortdict = from pair in dictBuff orderby pair.Key ascending select pair; 

    foreach (KeyValuePair<int, string> pair in sortdict) 
    { 
     dict.Add(pair.Key, pair.Value); 
    } 

foreach (var pair in dictBuff.OrderBy(x => x.Key)) 
    { 
     //dict.Add(pair.Key, pair.Value); 
     //meaningful code here 
    } 

UPDATE

你可以這樣做,而不是使用SortedDictionary另一件事情:使用List<KeyValuePair<int, string>>或Array而不是Dictionary<int, string>。迭代時的用法完全相同,但您將無法使用索引器,如list[someItem]。然後,您需要執行list.Single(x => x.Key == someItem)或使用FirstFirstOrDefault

//var sortedList = dictBuff.OrderBy(x => x.Key).ToArray(); 
var sortedList = dictBuff.OrderBy(x => x.Key).ToList(); 

應該這樣做。

+0

「字典僅僅是一個帶有每個元素的標識符的列表,所以元素將會按照他們放入的順序退回。「 - 這是錯誤的,枚舉.NET字典不一定會按照它們插入的順序返回項目。 – Joe

+0

它在內部就像一個列表。但它不是一個保證的行爲。 –

相關問題