-1

我对您在实现一个用于在 C# 中编写集成/系统测试的小型库时出现的问题的意见很感兴趣。该库由两部分组成:测试创作 API 和测试运行时 API。测试编写者使用创作 API 来构建测试计划原型。运行时可以获取原型并创建原型的运行时表示并执行它。

为了能够测试名为 RuntimeTestPlanBuilder 的类,我必须在整个运行时对象模型类上重写 Equals 方法。这导致了我也应该重写 GetHashCode 方法的情况。为一些运行时对象模型类实现 GetHashCode 很容易。由于运行时模型上的某些类是为它们实现 GetHashCode 的容器,这很难甚至是不可能的(例如,由于运行时可以将项目添加到容器中,因此无法在 O(1) 中计算哈希码)。

结果,我发现自己想知道如何防止容器的用户将它们作为键放在字典中。我选择的解决方案是重写 GetHashCode 方法并抛出异常。我对这个解决方案不满意,因为它只会在运行时失败。另外,我有点想知道为什么 .Net Framework 设计者选择将 GetHashCode 方法放在 Object 类上。我认为这个决定导致了我的情况,因为我不能很好地将我的容器标记为不合法的字典键。

一个更好的决定(对于 .Net Framework 设计人员)可能是定义一个名为 IHashable 的接口,其中包含 2 个方法:Equals 和 GetHashCode,并通过对通用字典 Item 类型的约束来强制执行该接口。这样我们可以在编译时强制键实现 Equals 和 GetHashCode。此外,很容易理解,不实现此接口的类不应该用作字典键。

我的问题是:您能否提出一个更好的解决方案(一个不会从 GetHashCode 引发异常的解决方案)来指定某些类的实例不应用作字典键?

谢谢

4

2 回答 2

0

一个 Object 应该实现五个方法,GetHashCode 就是其中之一。
无法确定 GetHashCode 当前或未来的唯一用途是用于 Dictionary 键。

唯一的规则是两个相等的对象必须具有相同的 GetHashCode。
但是相同的 GetHashCode 并不意味着两个对象相等。

您可以只对 GetHashCode 或容器中的项目数使用常量 (1)。
或者从 Skeet 看到这个答案

是否有可能组合哈希码为私有成员生成新哈希

于 2013-03-26T17:02:06.110 回答
0

一般来说,两个对象只有在它们相等且总是相等的情况下才应该将它们自己报告为相等;因此,可变对象(包括可变集合)通常只应被视为彼此相等。不可变集合可以GetHashCode通过缓存GetHashCode()其成员的值来有效地实现;构造是 O(N),无论哈希码是在对象构造上计算还是在第一次请求时计算,计算它的总生命周期成本最多为 O(N)。

任何类都没有理由难以实现哈希码。如果一个类使用引用相等,默认GetHashCode是完美的。如果它使用可变的相等定义,则GetHashCode()可以通过简单地返回一个常量来遵守合同。尝试将多个实例放入字典中可能会产生较差的性能,但可能有人可能会使用包含十几个项目的字典,并且对于这样大小的字典,性能会很好。

于 2013-11-19T00:07:33.557 回答