【问题标题】:Using a basic class as a dictionary key type? [duplicate]使用基本类作为字典键类型? [复制]
【发布时间】:2013-11-29 10:44:06
【问题描述】:

有点初级的问题,但这里是......

我经常使用字典来存储有关其他对象的辅助信息:

Dictionary<Person, int> timesAccessed;

Person p = // ...;
if (timesAccessed[p] == 0)
    // ...

假设我的“Person”类看起来像:

class Person
{
    public string Name;
}

请注意,我还没有在Person 上实现EqualsGetHashCode 等。字典仍然能够使用这样的键进行快速查找吗?由于Person 是一个类,而p 是引用,我可以想象它使用内存地址/一些内部索引作为哈希码,但我想确保它没有诉诸线性扫描字典。

【问题讨论】:

  • 测试很容易:创建一些 Person 对象并自己调用 GetHashCode()。它们会有所不同。
  • 这与@gdoron 所说的相反。所有实例都将给出单独的哈希码(即使 Name 具有相同的值 - 如果您想将包含相同数据的对象视为相等,这可能会使默认生成的哈希码成为一个糟糕的选择)

标签: c# dictionary


【解决方案1】:

在没有实现 Equals 或 IEqualityComparer 的情况下,即使是字典项的检索也是一种运气游戏。只要您请求完全相同的实例,它就会起作用,但是如果您请求与字典中的项目具有相同数据的新实例,则字典将找不到该项目。
因此,如果您想要字典的确定性行为,您要么必须在类本身上实现 Equals 和 GetHashCode。作为替代方案,如果您无法更改用作键的类或想要实施不同的比较规则,也可以使用上述 IEqualityComparer 选项:

private class PersonEqualityComparer : IEqualityComparer<Person>
{
    public bool Equals(Person p1, Person p2)
    {
        // Compare the strings as needed (culture, casing, nulls, ...)
        return p1.Name == p2.Name;
    }

    public int GetHashCode(Person p)
    {
        // Handle nulls as needed
        return p.Name.GetHashCode();
    }
}

创建字典时,可以在构造函数中提供相等比较器:

var dict = new Dictionary<Person, int>(new PersonEqualityComparer());

该接口还需要为目标类型实现 GetHashCode,因此我希望字典能够使用它来有效地查找项目。

【讨论】:

  • 我应该更清楚 - 我想要做的是纯粹基于引用而不是对象的值的查找。如果我创建两个具有相同名称的“Person”对象,我应该能够将它们作为两个单独的条目添加到我的字典中。我演示的方式允许这样做,因为它似乎默认使用引用相等。但是,由于这是一本字典,我希望它仍然可以进行 O(1) 查找,尽管我没有实现 GetHashCode。
  • @Barguast 是的,它可以正常工作。有关详细信息,请参阅此线程:ckoverflow.com/questions/720177/default-implementation-for-object-getashcode
猜你喜欢
  • 2016-09-26
  • 2017-07-16
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-11
  • 1970-01-01
相关资源
最近更新 更多