Why does the .Net Dictionary look like it is sorted?
我在看我的同事签入的代码,它看起来是这样的:
1
| return list.OrderBy(item => item.Order).ToDictionary(item => item.Id); |
我立即告诉我的同事他的代码是错误的,因为Dictionary是一个哈希表,一个未排序的集合。我说,他要么使用保存订单的收藏品,要么在以后用foreach从字典中读到的时候对这些物品进行分类。
但他回答说:"不,不,我的密码是正确的!看:既然我已经添加了OrderBy,那么这些项目的显示顺序是正确的。"
结果,在测试案例中,他是对的。我尝试了一些其他的数据,但它仍然是完美的排序!
我告诉他不应该依赖这种行为,但他不同意,我很难解释为什么。另外,我很感兴趣的是,为什么订单经常被保存。
所以我的问题是…为什么作为一个基本上没有排序的集合,Dictionary看起来像是排序的?
- Dictionary<>不保证集合无序。它不是故意随机使用的。是的,代码是错误的。
- 是的,贾斯汀,这是复制品。你链接的问题的答案是我想要的。在这么多关于词典的问题中,你怎么能这么快地找到副本呢?我找了找不到。谢谢您!
- 我不知道(这就是为什么我要将其作为注释发布),但我认为它与SQL中的情况相同:除非包含ORDER BY子句,否则SELECT返回的行以未指定的顺序返回。通常,尤其是在小数据集中,行的返回顺序与插入的顺序相同,这会使很多人感到困惑。(我总是告诉人们,如果他们关心结果的排序,就包括ORDER BY。如果没有它,它可能会工作,但也可能会严重损坏。)
- @Eldritchconundrum——这是谷歌在.net dictionary order上的第一个结果。我发现谷歌有时比内置搜索更有效。
由于实现Dictionary的方式(在您的案例中,项目是按顺序添加的),所以对它进行排序。但这是实现细节。
告诉你的同事有一个SortedDictionary类存在,这应该能让他相信我们不能依赖简单的Dictionary;的项目订单。
- 当然,这是一个实现细节,但我认为不会改变。也许可以说add()-只有字典才能保持顺序。
- @Eldritchconundrum真的,你不应该这么认为。目前是这样,但在未来的版本中可能不是这样。考虑到框架的其他实现(例如mono),不能保证它们以相同的方式实现字典。
- 对。更重要的是,现在我知道了如何构建一个测试用例,我的同事的代码将失败;我只需要在foreach之前删除和添加。
当遍历字典时,您将按照插入字典的顺序获取其中的项。
在这个例子中,一个列表被排序,然后每个条目依次添加到字典中。
最终的结果是字典中的项按列表的排序顺序排列。
然而,这种情况恰好发生在当前执行Dictionary的情况下——不能保证它会保持这种状态。
如果您需要在一个特定的顺序中拥有一个Dictionary中的项目,您应该使用一个SortedDictionary。
- 你能更好地解释一下为什么要分类吗?我想说,它们是由散列"排序"的,散列是"i d"属性。
- @路易斯菲利佩-我不明白。列表被订购(list.OrderBy(item => item.Order),然后转换为Dictionary。转换的工作方式是将每个项添加到字典中。字典中的项目按插入顺序"排序"。因为它们是按顺序插入的,所以字典是按顺序插入的。
- 这是由规范/合同来保证的,还是由编写特定实现的方式造成的?如果它是有保证的行为,引用将是有用的。
- @Michaelkj&246;rling-没有保证,只是目前版本的Dictionary是如何实现的。
- 是的,我在添加评论后看到了你的编辑。:)
- 实际上,键是以散列依赖的顺序存储的,但值不是,字典枚举器使用值存储。
- @埃尔德里奇难题:谢谢你的评论