Does the Enumerator of a Dictionary<TKey, TValue> return key value pairs in the order they were added?
我知道字典不是有序的集合,不应该依赖于字典中插入和检索的顺序。
然而,这正是我注意到的:
- 在字典中添加了20个键值对
- 通过执行foreach(keyValuePair…)检索到它们
检索顺序与添加顺序相同。测试了大约16个键值对。
这是设计的吗?
这是巧合,尽管可以预见。你绝对不应该依赖它。通常在简单的情况下会发生这种情况,但是如果您开始删除元素并用相同的哈希代码替换它们,或者只是进入同一个bucket,那么该元素将占据原始元素的位置,尽管添加的时间比其他元素晚。
复制这个相对比较费劲,但我在不久前就设法做到了另一个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System; using System.Collections.Generic; class Test { static void Main(string[] args) { var dict = new Dictionary<int, int>(); dict.Add(0, 0); dict.Add(1, 1); dict.Add(2, 2); dict.Remove(0); dict.Add(10, 10); foreach (var entry in dict) { Console.WriteLine(entry.Key); } } } |
结果显示10,1,2而不是1,2,10。
请注意,即使当前行为看起来总是按插入顺序生成元素,如果不执行任何删除操作,也不能保证将来的实现也会执行相同的操作…所以,即使在你知道不会删除任何内容的受限情况下,也不要依赖于此。
来自msdn:
For purposes of enumeration, each item in the dictionary is treated as a
KeyValuePair<(Of <(TKey, TValue>)>) structure representing a value and its key. The order in which the items are returned is undefined.
号
[添加强调]
如果要按固定顺序迭代字典,可以尝试ordereddictionary。
根据设计,
如果您需要按照特定的顺序检索项目,您应该查看
这是设计的吗?它可能不在原始的.NET Framework 2.0中,但现在有一个隐式契约,它们的顺序与添加的顺序相同,因为要更改它,将破坏太多依赖于原始通用字典行为的代码。与Go语言相比,它们的映射故意返回随机顺序,以防止映射用户依赖于任何顺序[1]。
框架编写者对DictionaryDocx1(7)所做的任何改进或更改都必须保持这种隐含的契约。
[1]"自从Go 1.0发布以来,运行时具有随机映射迭代顺序。",https://blog.golang.org/go-maps-in-action。
我相信枚举
我不这么认为,这本词典并没有授权对里面的条目进行内部排序。如果您还需要保持顺序,请使用附加的数据结构(数组或列表)和字典。