2014-01-23 30 views
0

當字典被轉換成一個列表,並在列表的順序關聯到物品進入字典的插入順序。在這個例子中,插入順序被保留,但是這種情況總是如此?或者,它是如何字典決定存儲其項目。字典到列表廣告訂單

 Dictionary<string, int> test = new Dictionary<string, int> 
    { 
     {"A",0}, 
     {"Z",1}, 
     {"F",2}, 
     {"J",3} 
    }; 

    List<KeyValuePair<string, int>> testlist = 
     new List<KeyValuePair<string,int>>(test); 
+0

可能會有所幫助:http://stackoverflow.com/questions/7387874/is-there-a-an-easier-way-to-initialize-a-listkeyvaluepairt-u-like-a-dictio – Habib

回答

2

知道肯定這一點的唯一方法是看代碼,所以讓我們做...

您呼叫的List<T>,反編譯的時候構造函數的實現,貌似

public List(IEnumerable<T> collection) 
{ 
    if (collection == null) 
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); 
    ICollection<T> collection1 = collection as ICollection<T>; 
    if (collection1 != null) 
    { 
    int count = collection1.Count; 
    if (count == 0) 
    { 
     this._items = List<T>._emptyArray; 
    } 
    else 
    { 
     this._items = new T[count]; 
     collection1.CopyTo(this._items, 0); 
     this._size = count; 
    } 
    } 
    else 
    { 
    this._size = 0; 
    this._items = List<T>._emptyArray; 
    foreach (T obj in collection) 
     this.Add(obj); 
    } 
} 

正如你所看到的,字典轉換爲ICollection<T>,然後CopyTo叫上這使我們Dictionary<TKey, TValue>

private void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) 
{ 
    if (array == null) 
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); 
    if (index < 0 || index > array.Length) 
    ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); 
    if (array.Length - index < this.Count) 
    ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); 
    int num = this.count; 
    Dictionary<TKey, TValue>.Entry[] entryArray = this.entries; 
    for (int index1 = 0; index1 < num; ++index1) 
    { 
    if (entryArray[index1].hashCode >= 0) 
     array[index++] = new KeyValuePair<TKey, TValue>(entryArray[index1].key, entryArray[index1].value); 
    } 
} 

從查看代碼中,字典的內部項目是,索引爲

基於這些發現,如果你問是「會當它轉化爲一個泛型列表我的字典順序予以保留?」 - 那麼是的它會(根據.NET 4.0,這是我正在看的版本)。但是,問題在於,您實際上無法保證將項目的順序添加到字典開始。因此,我的建議將轉換爲使用OrderedDictionary<T>之類的東西,或者在轉換它之前應用OrderBy子句,例如

var list = new List<KeyValuePair<K, V>>(test.OrderBy(x => x.Value)); 
+1

你說的是真的,但問題是「列表的順序是否與項目插入到詞典中的順序相關?」你應該說一些將你的答案與訂單項目最初插入到'Dictionary'中的東西。 –

+0

「你可以肯定」現在在你的.NET版本上(你真的確定它們都是一樣的嗎?OP沒有說明他使用的是什麼版本)。我認爲OP會希望今天編寫代碼,明天行爲方式相同。不保證未來的.NET補丁/版本不會改變無證內部行爲 –

+0

@MagnusHoff我選擇問題的方式是「*當我創建基於字典的新列表時,我的項目是否以相同的順序* 「所以我的回答是基於此。我會更新澄清。 AZ。沒錯,我會爲此添加一個免責聲明。 – James

0

標準Dictionary<TKey, TValue>確實通常保留插入順序,但這可能無法得到保證,你不應該依賴於它。

MSDN

「對於枚舉的目的,字典中的每個項被視爲一個結構KeyValuePair代表值及其鍵,其中所述的數據項都返回未定義的順序。」

+0

我認爲如果它確實維持秩序,通常只是巧合,看[實施](http://www.dotnetframework.org/default.aspx/[email protected]/[email protected]/untmp/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/clr/src/BCL/System/Collections/Generic/Dictionary @ cs/1305376/Dictionary @ cs)'Insert'它使用密鑰的HashCode來計算它的順序。 – James

+0

它通常會這樣,但不管怎樣都不應該依賴它。 – Haney

4

NO。它不保存順序。如果確實如此,那只是意外和內部實現細節。不能保證元素的枚舉順序應與插入順序相同。 文檔states

項目返回的順序是未定義的。

+2

爲什麼這麼多downvotes一個正確的答案?或者你們是否試圖暗示關於沒有記錄,容易發生變化和意外實施的細節有待鼓勵? –

1

解釋並不能保證項目的順序。

,如果你想保持在那裏加入到它的訂單項目需要OrderedDictionary