2014-01-23 2 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

То, что вы говорите, верно, но вопрос заключается в том, «упорядочивает ли список список в порядке размещения элементов в словаре?» Вы должны сказать что-то, что связывает ваш ответ с элементами заказа, которые первоначально были вставлены в «Словарь». –

+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.

Смежные вопросы