我需要使用Dictionary<long, string>
给定两个实例的集合,d1
并且d2
它们每个都具有相同的KeyValuePair<long, string>
内容,可以按任何顺序插入:
(d1 == d2)
评估为true
d1.GetHashCode()
==d2.GetHashCode()
通过使用 aSortedDictionary
而不是常规的 ,最容易实现第一个要求Dictionary
。
第二个要求是必要的,因为我有一个需要存储Dictionary<Dictionary<long, string>, List<string>
的点 - 主要Dictionary
类型用作另一个的键Dictionary
,如果 HashCodes 不基于相同的内容进行评估,则 usingContainsKey()
将无法按我想要的方式工作(即:如果已经有一个项目插入到字典中,d1
作为它的键,那么dictionary.ContainsKey(d2)
应该评估为true
.
为此,我创建了一个新对象class ComparableDictionary : SortedDictionary<long, string>
,并包含以下内容:
public override int GetHashCode() {
StringBuilder str = new StringBuilder();
foreach (var item in this) {
str.Append(item.Key);
str.Append("_");
str.Append(item.Value);
str.Append("%%");
}
return str.ToString().GetHashCode();
}
在我的单元测试中,这符合相等和哈希码的标准。但是,在阅读GetHashCode 的指南和规则时,我遇到了以下问题:
规则:当对象包含在依赖于哈希码保持稳定的数据结构中时,GetHashCode 返回的整数永远不能改变
虽然很危险,但允许对象的哈希码值随着对象的字段发生变异而发生变异是允许的。如果你有这样一个对象并且你把它放在一个哈希表中,那么改变对象的代码和维护哈希表的代码需要有一些商定的协议,以确保对象在它存在时不会发生变异哈希表。该协议的外观取决于您。
如果对象的哈希码在哈希表中时可能会发生变异,那么显然 Contains 方法将停止工作。您将对象放入存储桶#5,对其进行变异,当您询问集合是否包含变异对象时,它在存储桶#74 中查找并没有找到它。
请记住,对象可以以您意想不到的方式放入哈希表中。许多 LINQ 序列运算符在内部使用哈希表。不要在枚举返回对象的 LINQ 查询时危险地改变对象!
现在,在代码中只使用一次,在一个应该设置Dictionary<ComparableDictionary, List<String>>
所有集合的内容的地方。ComparableDictionary
因此,根据这些准则,我认为像我所做的那样覆盖是可以接受的GetHashCode
(完全基于字典的内容)。
在介绍之后,我的问题是:
- 我知道与(我可以有数百个对象实例化)
SortedDictionary
相比,它的性能非常差。Dictionary
使用的唯一原因SortedDictionary
是我可以根据字典的内容进行相等比较工作,而不管插入顺序如何。有没有更好的方法来实现这个平等要求而不必使用 aSortedDictionary
? GetHashCode
根据要求,我的实施是否可以接受?即使它基于可变内容,我认为这不会带来任何风险,因为它唯一使用的地方(我认为)是在设置内容之后。
注意:虽然我一直在使用Dictionary
or设置这些SortedDictionary
,但我并不喜欢这些集合类型。主要需求是一个可以存储值对并满足上面定义的相等和散列要求的集合。