9

在 C# 中为类创建自己的 GetHashCode 方法的最佳方法是什么?假设我有一个简单的类(它覆盖了 Equals 方法),如下所示:

class Test
{
   public string[] names;

   public double[] values;

   public override bool Equals(object obj)
   {
      return (obj is Test) && this.Equals((Test)obj);
   }

   public bool Equals(Test t)
   {
      return names.Equals(t.names) && values.Equals(t.values);
   }
}

我应该使用 GetHashCode 方法的默认代码吗?

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

我应该基于我的课程内容的方法吗?

public override int GetHashCode()
{
   return names.GetHashCode() + values.GetHashCode() ;
}

还是我应该做点别的?

4

4 回答 4

12

System.Array不会覆盖GetHashCodeor Equals,因此它们使用引用相等。因此,您不应该打电话给他们。

要实施GetHashCode,请参阅此问题

要实现Equals,请使用SequenceEqual扩展方法。

编辑:在 .Net 2.0 上,您必须编写自己的版本SequenceEqual,如下所示:

public static bool SequenceEquals<T>(IList<T> first, IList<T> second) {
    if (first == second) return true;
    if (first == null || second == null) return false;

    if (first.Count != second.Count) return false;

    for (int i = 0; i < first.Count; i++)
        if (!first[i].Equals(second[i]))
            return false;

    return true;
}

你可以把它写成 takeIEnumerable<T>而不是IList<T>,但它会有点慢,因为如果参数有不同的大小,它就不能提前退出。

于 2009-07-22T15:36:22.333 回答
2

确保将 .GetHashCode() 的覆盖与 .Equals() 保持同步非常重要

基本上,您必须确保他们考虑相同的字段,以免违反 GetHashCode 的三个规则中的第一个(来自MSDN object.GetHashCode()

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

换句话说,您必须确保每次 .Equals 认为两个实例相等时,它们也将具有相同的 .GetHashCode()。

正如其他人在这里提到的,这个问题详细介绍了一个很好的实现。如果您有兴趣,我在去年初写了几篇关于调查哈希码的博客文章。你可以在这里找到我的漫谈(我写的关于这个主题的第一篇博文)

于 2009-07-22T15:46:29.163 回答
1

这里对这些问题进行了很好的讨论,最近的更新参考了 SharpArchitecture 提供的BaseObject 抽象类

如果您想要更特别的东西,我发现 ReSharper 为 Equals() 和 GetHashCode() 生成的代码很好。

于 2009-07-22T16:29:14.953 回答
1

如果你使用 dotnetcore 2.1+,你可以使用HashCode struct 的Combile方法来处理所有的属性,使用起来非常简单而且效率很高。

于 2019-11-15T14:18:18.460 回答