重写 GetHashCode 方法是否意味着使用的值永远不应该改变?

问题描述 投票:0回答:1

如果我有一个具有属性的类

public class a{
    public int b;
    public int c;
    public int d;
}

我重写了类中的 GetHashCode 方法

public class a
{
    public int b;
    public int c;
    public int d;

    public override int GetHashCode()
    {
         int hashCode = base.GetHashCode();
         hashCode = hashCode * -1521134295 + a.GetHashCode();
         hashCode = hashCode * -1521134295 + b.GetHashCode();
         hashCode = hashCode * -1521134295 + c.GetHashCode();
         return hashCode;
    }

   public override bool Equals(){
   ...
   }
}

这是否意味着 a、b 或 c 永远不应该改变?否则 GetHashCode 方法就没用了?由于更改属性会生成不同的哈希码,并且某个时间的对象不等于以后另一个状态的对象?通常这应该是正确的,但我遇到了奇怪的绑定问题,似乎表明我不应该这样做。

我想我正在读一些关于这个的东西,但我想验证这是真的。似乎对象的属性一直在变化,所以在我的 99% 的用例中覆盖 GetHashCode() 似乎都不安全,在这些用例中你不希望在更改对象时破坏东西,如果是这样的

谢谢。

无反推覆盖

c# gethashcode
1个回答
1
投票

基本上是的,如果您在依赖哈希码值存储它的某些数据结构中使用该类(例如字典中的键),那么用于计算哈希码的值应该保持不变。

Object.GetHashCode
的文档有一个关于此主题的部分,称为 继承人注释。简而言之,您应该尝试避免覆盖可变引用类型的
GetHashCode

您可以为不可变引用类型覆盖

GetHashCode()
。通常,对于可变引用类型,只有在以下情况下才应该重写
GetHashCode()

  • 您可以从不可变的字段计算哈希码;
  • 您可以确保当对象包含在依赖于其哈希码的集合中时,可变对象的哈希码不会改变。

否则,您可能会认为可变对象丢失在哈希表中。如果您确实选择为可变引用类型覆盖

GetHashCode()
,您的文档应该明确说明您的类型的用户不应在对象存储在哈希表中时修改对象值。

类似的建议也可以在Equality Operators doc.

中找到
© www.soinside.com 2019 - 2024. All rights reserved.