在通用字典</tkey>上使用IEqualityComparer <tkey>的用例

时间:2011-05-02 09:11:09

标签: c# generics

今天在研究项目时,我正在浏览Dictionary<TKey, TValue>的文档。在那里,我发现了一些我过去可能忽略的评论:

因为密钥可以被继承并且它们的行为发生了变化,所以使用Equals方法进行比较无法保证它们的绝对唯一性。

在我之后看到的大多数(键控)集合类的文档中,似乎都有同样的评论。但是我无法找到任何说明所描述的潜在问题的例子,尽管我很确定这是构造函数接受IEqualityComparer<TKey>的原因,并且当复杂类型被用作密钥。

任何人都可以向我解释在哪种情况下可能会遇到这个评论指出的问题?只要我不确切知道如何或何时出现这样的问题,我就无法设计允许它。

2 个答案:

答案 0 :(得分:2)

使用任何对象/值作为键并不像听起来那么简单,因为它取决于Equals和GetHashCode的正确实现。说实话,“子类扭曲事物”场景并不是我遇到过的场景,但是这个API的更常见用途是允许在你使用的类型作为键时没有提供合适的Equals / GetHashCode时使用,并且超出了你的控制范围。例如,您希望使用Customer作为键,但您只想匹配Id(即您不希望默认的引用相等行为;也许您正在处理来自不同的不同对象根据{{​​1}},需要将不同的实例视为相等。在这种情况下,您可以编写仅考虑Id

的自定义相等比较器

但是,个人而言;我是一个简单的粉丝。我 很少 (如果有的话)索引除Idint等之外的任何内容。这样可以保持简单 - 同时显示另一种常见情况:为string密钥提供区分大小写/不区分大小写或文化敏感/不敏感的比较器。

答案 1 :(得分:1)

Takrl,

假设你在服务器上处理一个大的查询结果:你正在构建一个大的Dictionary<Student, List<Result>> ...同时有人 - 其他人改变了一个Student对象的身份在你下面的共享模型中(比如有人将“Bob”的名字改为“Fred”)。如果Name属性有助于Student'Equals(和HashCode)方法,那么当您下次尝试将“Bob”的结果添加到Dictionary时,您将无法在Dictionary中找到对象 - 其中代表Bob,因为“Bob”对象的HashCode已经改变了...所以他现有的结果“丢失了”。

因此:使用任何类作为键的一个技巧是使其标识字段(在equals和HashCode方法中使用的那些)不可变。< / p>

实际上,在您同时从多个线程访问模型之前,这无关紧要。在单线程环境中,您真的不必担心,只是因为在您需要的时候,您不会愚蠢地改变您需要的身份。

这有意义吗?

干杯。基思。