.net 如何指定某个类';s实例不应用作字典键?

.net 如何指定某个类';s实例不应用作字典键?,.net,equals,gethashcode,.net,Equals,Gethashcode,我对您在实现一个小型库(用于用C#编写集成/系统测试)时提出的一个问题的看法很感兴趣。图书馆由四部分组成 2部分:测试编写API和测试运行时API。测试编写器使用编写API来构建测试计划原型。运行时可以获取原型并创建 原型的运行时表示并执行它 为了能够测试名为RuntimeTestPlanBuilder的类,我必须在整个运行时对象模型类上重写Equals方法。这导致了我也应该重写GetHashCode方法的情况。为一些运行时对象模型类实现GetHashCode很容易。由于运行时模型上的某些类是实

我对您在实现一个小型库(用于用C#编写集成/系统测试)时提出的一个问题的看法很感兴趣。图书馆由四部分组成 2部分:测试编写API和测试运行时API。测试编写器使用编写API来构建测试计划原型。运行时可以获取原型并创建 原型的运行时表示并执行它

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

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

(对于.Net Framework设计人员而言)更好的决策可能是使用两种方法定义名为IHashable的接口:Equals和GetHashCode,并使用对泛型字典项类型的约束强制该接口。通过这种方式,我们可以在编译时强制键实现Equals和GetHashCode。另外,不实现此接口的类不应该用作字典键,这一点很容易理解

我的问题是:您能提出一个更好的解决方案(不从GetHashCode抛出异常的解决方案)来说明某些类的实例不应该用作字典键吗


谢谢

一个对象应该实现五种方法,GetHashCode就是其中之一。
无法确定GetHashCode当前或将来的唯一用途是字典键

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

您可以使用一个常量(1)来表示GetHashCode或容器中的项目数。
或者从飞碟上看到这个答案


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


任何类都没有理由在实现哈希代码时遇到困难。如果类使用引用相等,则默认的
GetHashCode
是完美的。如果它使用可变的相等定义,则只需返回一个常量即可遵守
GetHashCode()
契约。尝试将多个实例放入字典可能会产生较差的性能,但可能有人会使用一个包含十几个项的字典,而对于这样大小的字典,性能会很好。

您如何在问题类上实现Equals()方法?实现GetHashCode()应该不会比实现Equals()困难。基本上,如果两个容器的项目数相同,那么它们是相等的,相同位置的所有项都是相等的。@PieterGeerkens-请不要在指定的上下文中而是在更广泛的上下文中思考我的问题-如何将某些类标记为不合法的字典键?您问的问题是错误的,因为您误解了Equals()和GetHashCode()之间的关系。在计算哈希代码时,只能使用与Equals()相关的字段/属性,因为必须确保
相等的两个对象返回相同的哈希代码。此外,当对象在字典中时,用于计算对象哈希的字段/属性不能有任何更改。然后不要将Random用作字典键。Random仍然实现GetHasCode。一个对象应该实现五个方法,GetHashCode就是其中之一。您如何确定GetHashCode当前或将来的唯一用途是字典键。