我对您在实现用于在C#中编写集成/系统测试的小型库时出现的问题感兴趣。图书馆由 2部分:测试Authoring API和测试Runtime API。测试编写者使用创作API来构建测试计划原型。运行时可以获取原型并创建一个 原型的运行时表示并执行它。
为了能够测试名为RuntimeTestPlanBuilder的类,我不得不在整个运行时对象模型类上重写Equals方法。这导致了我应该重写GetHashCode方法的情况。为某些运行时对象模型类实现GetHashCode很容易。由于运行时模型上的某些类是实现GetHashCode的容器,因此很难甚至不可能(因为运行时可以向容器添加项,因此无法在O(1)中计算哈希代码)。
结果我发现自己想知道如何阻止容器的用户将它们作为键放在字典上。我选择的解决方案是覆盖GetHashCode方法并抛出异常。我对此解决方案不满意,因为它只会在运行时失败。另外,我有点想知道为什么.Net Framework设计者选择将GetHashCode方法放在Object类上。我认为这个决定导致了我的情况,因为我无法将我的容器标记为不合法的字典键。
更好的决定(对于.Net Framework设计者)可能是使用2种方法定义名为IHashable的接口:Equals和GetHashCode,并使用对通用字典Item类型的约束来强制实施接口。这样我们就可以在编译时强制执行密钥实现Equals和GetHashCode。此外,很容易理解,不实现此接口的类不应该用作字典键。
我的问题是:你能提出一个更好的解决方案(不会从GetHashCode中抛出异常),以指出某些类的实例不应该用作字典键吗?
由于
答案 0 :(得分:0)
一个Object应该实现五个方法,而GetHashCode就是其中之一 无法确定GetHashCode当前或将来的唯一用途是否为Dictionary键。
唯一的规则是两个相等的对象必须具有相同的GetHashCode 但是相同的GetHashCode并不意味着两个对象是相同的。
您可以使用常量(1)表示GetHashCode或容器中的项目数 或者从Skeet
看到这个答案is-it-possible-to-combine-hash-codes-for-private-members-to-generate-a-new-hash
答案 1 :(得分:0)
一般来说,两个对象只应报告自己是相等的,如果它们总是等同的话。因此,可变对象(包括可变集合)通常应被视为彼此相等。不可变集合可以通过缓存其成员的GetHashCode
值来有效地实现GetHashCode()
;构造是O(N),无论是在对象构造上计算哈希码还是在第一次请求时计算哈希码,计算它的总寿命成本最多为O(N)。
没有理由任何类应该在实现哈希码时遇到困难。如果类使用引用相等,则默认GetHashCode
是完美的。如果它使用可变的相等定义,则可以通过简单地返回常量来遵守GetHashCode()
契约。试图将多个实例放入字典可能会产生较差的性能,但有可能某人可能会使用字典,例如其中有十几个项目,如果字体大小,性能会很好。