在内存中具有不同引用的两个对象,它们的.GetHashCode()返回相同的值吗?

4

我需要为我的某种类型覆盖Equals()方法,但似乎我还必须覆盖GetHashCode()方法。

我不确定:

如果我有一个动物类型,并且我有两个实例的动物,它们基本上是相同的(相等)猫;像:

Animal cat_01 = new Animal("Kitty", "Pink");
Animal cat_02 = new Animal("Kitty", "Pink");

我应该实现GetHashCode()方法, 以便对于内存中不同引用的cas_01和cat_02返回相同的值吗?

这是GetHashCode()方法应该工作的方式吗?

谢谢


2
基本上,您的Animal类可能不应该覆盖Equals,GetHashCode或==。如果您这样做,还应将其设计为不可变。另请参见MattDavey的答案。 - H H
3个回答

4

MSDN说:

如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。

所以,是的,GetHashCode应该为这两个实例返回相同的值。

如果您想要查看它们是否引用同一个对象,仍可以使用Object.ReferenceEquals。


2
对于未来遇到这个问题的任何人,提供一些信息 - 这并不是所有情况下的正确答案。在面向对象编程方面,需要考虑实体何时应被视为相等,何时不应该。仅仅因为两个对象具有相似的属性就认为它们总是相等,这通常是错误的。 - MattDavey
2
我的回答只是回答了一个基本问题:当Equals返回true时,GetHashCode是否应该为两个对象返回相同的值?当然,覆盖equals在这种情况下是否有意义,则是另一回事。 - Botz3000

3
我不同意其他答案。在这个例子中,动物不是一个值对象,两只猫有相同的名字和颜色并且是完全不同的实体是完全可行的。从逻辑上讲,你是在说“这只猫和那只猫有相同的名字和相同的颜色,因此它们是同一只猫”——这并不一定是正确的。
我建议您保留Animal.Equals的默认实现,并创建一个单独的IEqualityComparer实现,如果动物具有相同的名称/颜色,则返回true。
public class AnimalNameColorComparer : IEqualityComparer<Animal>
{
    public bool Equals(Animal a, Animal b)
    {
        return a.Name == b.Name &&
               a.Color == b.Color
    }

    public int GetHashCode(Animal a)
    {
        return a.Name.GetHashCode() ^ a.Color.GetHashCode();
    }
}

请记住,比较猫的方法有很多种,单一的“等于”方法是不够的 :)

// Create two black cats called fluffy...
var cat1 = new Cat("Fluffy", "Black");
var cat2 = new Cat("Fluffy", "Black");

cat1.Equals(cat2) == false; // they are not the same cat!

var comparer = new AnimalNameColorComparer();

comparer.Equals(cat1, cat2) == true; // But they do have the same name & colour...

这个问题特别涉及到实现GetHashCode,这是字典类型查找中使用的键的特殊要求。如果发生碰撞,生成哈希码后会考虑相等性。 - Tim Lloyd
如果你在评论中提到了非作者用户,你应该引用他们的@用户名,否则他们将不会收到通知。 - Tim Lloyd
3
+1 表示不回答问题,但指出导致问题的设计错误。 - H H
回到主题 - 通过重写 GetHashCode,您不能在字典中拥有两只名字和颜色相同的猫,这是否真的是期望的程序行为?在这种情况下,将 GetHashCode 和 Equals 留给它们的默认实现是正确的做法。 - MattDavey
1
@Matt 是的,你可以在字典中拥有两只名字和颜色相同的猫,但它们存储的键必须不同。GetHashCode是在上调用的。 - Tim Lloyd
2
这是一个很好的观点,但我认为我们可以相当确定提问者实际的类不是Animal,因此现实世界中动物并不是通过它们的名称和颜色唯一标识的(这是绝对正确的),这并不一定适用。请注意,问题文本包括“基本上是相同的”,这表明对于实际的类,这两个成员的相等性确实意味着身份的相等性。 - AakashM

1

根据模型的设计,如果它是值对象(不可变),那么gethashcode应该返回所有字段的哈希值,但另一方面,如果它是域实体,则应该有一个标识,并且此标识应在比较和gethashcode中使用(具有相同名称和年龄的两个人不是同一个人,如果您有两只同名的猫,这并不意味着它们是同一只猫!)。

查看:http://moh-abed.com/2011/07/13/entities-and-value-objects/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接