字典列出插入顺序

时间:2014-01-23 15:34:45

标签: c# dictionary

当“词典”转换为“列表”时,“列表”的顺序是否与“词典”中项目的插入顺序相关。在此示例中,保留了插入顺序,但总是这样吗?或者是字典决定如何存储其项目。

     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);

4 个答案:

答案 0 :(得分:4)

NO。它不保留订单。如果它只是偶然和内部实现细节。无法保证元素的枚举顺序应与插入顺序相同。 文档states

未定义项目的返回顺序。

答案 1 :(得分:3)

确定这一点的唯一方法是查看代码,让我们这样做......

在反编译时,您调用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));

答案 2 :(得分:2)

字典不保证商品的顺序。

如果您想维护添加到其中的订单商品,则需要OrderedDictionary

答案 3 :(得分:0)

标准Dictionary<TKey, TValue> 通常会保留广告订单,但这可能无法保证,您也不应该依赖它。

来自MSDN

  

“为了枚举的目的,字典中的每个项目都被视为表示值及其键的KeyValuePair结构。返回项目的顺序是未定义的。”