为啥我需要覆盖 C# 中的 .Equals 和 GetHashCode [重复]

Posted

技术标签:

【中文标题】为啥我需要覆盖 C# 中的 .Equals 和 GetHashCode [重复]【英文标题】:Why do I need to override the .Equals and GetHashCode in C# [duplicate]为什么我需要覆盖 C# 中的 .Equals 和 GetHashCode [重复] 【发布时间】:2013-08-11 04:36:31 【问题描述】:

我正在使用 Entity Framework 5。在我的 C# 代码中,我想比较两个对象是否相等。如果没有,那么我想发布更新。

有人告诉我我需要重写 .Equals 方法,然后还要重写 gethascode 方法。我的课程如下所示:

public class Students    
    public int PersonId  get; set; 
    public string Name  get; set; 
    public int Age get; set; 

能否解释一下为什么我需要重写 .Equals 和 .GetHashCode。也有人可以给我一个例子。特别是我不确定哈希码。请注意,我的 PersonId 是此类的唯一编号。

【问题讨论】:

***.com/questions/371328/… @Melina 您在 cmets 中多次询问为什么需要覆盖 GetHashCode。请阅读@CodeIgnoto 链接到的问题的答案 【参考方案1】:

出于多种原因,您需要重写这两种方法。例如,GetHashCode 用于在DictionaryHashTable 中进行插入和查找。 Equals 方法用于对象的任何相等测试。例如:

public partial class myClass

  public override bool Equals(object obj)
  
     return base.Equals(obj);
  

  public override int GetHashCode()
  
     return base.GetHashCode();
  

对于GetHashCode,我会这样做:

  public int GetHashCode()
  
     return PersonId.GetHashCode() ^ 
            Name.GetHashCode() ^ 
            Age.GetHashCode();
  

如果你覆盖GetHashCode 方法,你也应该覆盖Equals,反之亦然。如果在测试两个对象是否相等时,覆盖的 Equals 方法返回 true,则覆盖的 GetHashCode 方法必须为这两个对象返回相同的值。

【讨论】:

我想他说的ID是唯一的^ 是的 ID 是唯一的。我可以将它用于哈希码吗?为什么我需要创建一个 GetHashCode。它是如何使用的? @Melina 如果您正在使用哈希表、字典或其他一些东西,则调用 GetHashCode 来获取类的哈希。您只能从 id 进行散列,但这是您的选择,我会对所有成员进行散列,但如果 ID 确实是唯一的,这不是强制性的 谢谢,但我一直听到“如果我覆盖 .Equals”,我需要覆盖 GetHashCode。所以如果我通常不覆盖 .Equals 我还需要覆盖 .GetHashCode 吗? @Melina 如果您不覆盖 Equals,并且不打算使用字典、列表或其他数据结构并且不需要比较不同的类型,那么您可能不需要覆盖这两者, 否则你应该,如果你覆盖等号,你肯定应该覆盖 hashCode【参考方案2】:

类是引用类型。当您创建两个对象并将它们存储在变量中时,您只是存储对它们的引用。这意味着如果您尝试比较它们,您只会比较两个引用,只有当它们指向堆上的同一个对象时它们才会相等。如果你想改变这种行为,你必须覆盖Equals。 还有一些集合依赖GetHashCode 将元素存储在树状(或任何其他)结构中,这些结构需要在给定类的两个对象之间进行比较。如果您需要定义的类在指定情况下正确运行,这就是为什么您需要实现这些方法的原因。GetHashCode 的典型实现是类字段的异或,在@No Idea For Name 的答案中给出。但由于 PersonId 在您的示例中是唯一的,您也可以使用它:

public int GetHashCode()

   return PersonId.GetHashCode();

【讨论】:

谢谢。现在我明白了。至于GetHashCode。为什么需要它?当我的 ID 是唯一的时,您如何建议我应该对其进行编码? @Melina,同样的原因。 GetHashCode(用于对象)的默认实现基于引用比较。作为一项规则,GetHashCode 应该表现出与Equals 相同的行为(尽管存在哈希冲突)。 @Melina 您只需返回 PersonId 的哈希码。而且我相信我已经解释了为什么它必须被覆盖。如果仍不清楚,请具体说明。

以上是关于为啥我需要覆盖 C# 中的 .Equals 和 GetHashCode [重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥我需要覆盖 Java 中的 equals 和 hashCode 方法?

为啥 StringBuffer/StringBuilder 不覆盖 equals 或 hashCode?

来自 C# 的 mingw DLL:为啥我必须覆盖新/删除?

为啥 set.contains 不使用覆盖的 equals() 方法?

覆盖 Java 中的 hashCode() 和 equals() 方法

C#中的g.DrawImage问题,请教一下,为啥ShowPic()不显示图片?