在C#中创建GetHashCode方法

时间:2009-07-22 15:32:42

标签: c# .net hashcode gethashcode

在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 个答案:

答案 0 :(得分:12)

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

要实施GetHashCode,请参阅this question

要实施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;
}

您可以将其编写为IEnumerable<T>而不是IList<T>,但它会稍慢,因为如果参数的大小不同,它将无法提前退出。

答案 1 :(得分:2)

确保使用.Equals()在步骤中保留.GetHashCode()的覆盖非常重要。

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

  

如果两个对象相等,那么   每个对象的GetHashCode方法   必须返回相同的值。然而,   如果两个对象不比较   等于,GetHashCode方法   两个对象不必返回   不同的价值观。

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

正如此处其他人所述,this question详细说明了良好的实施方式。 如果你感兴趣的话,我在去年年初写了几篇关于调查哈希码的博客文章。你可以找到我的ramblings here(我在这个主题上写的第一篇博文)

答案 2 :(得分:1)

对问题here进行了很好的讨论,最新的更新是指SharpArchitecture提供的BaseObject abstract class

如果您想要更多 ad hoc ,我发现ReSharper为Equals()和GetHashCode()生成的代码很好。

答案 3 :(得分:0)

如果您使用dotnetcore 2.1+,则可以对所有属性使用HashCode结构的Combile方法,这是非常容易使用和高效的。