简体   繁体   English

在C#中创建GetHashCode方法

[英]Creating the GetHashCode method in C#

What is the best way to create your own GetHashCode method for a class in C#? 在C#中为类创建自己的GetHashCode方法的最佳方法是什么? Suppose I have a simple class (which overrides the Equals method), as follows: 假设我有一个简单的类(它重写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);
   }
}

Should I use the default code for the GetHashCode method? 我应该对GetHashCode方法使用默认代码吗?

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

Should I base the method on the contents of my class? 我应该基于类的内容来创建方法吗?

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

Or should I do something else? 还是我应该做别的事情?

System.Array does not override GetHashCode or Equals , so they use reference equality. System.Array不会重写GetHashCodeEquals ,因此它们使用引用相等。 Therefore, you shouldn't call them. 因此,您不应致电给他们。

To implement GetHashCode , see this question . 要实现GetHashCode ,请参见此问题

To implement Equals , use the SequenceEqual extension method. 要实现Equals ,请使用SequenceEqual扩展方法。

EDIT : On .Net 2.0, you'll have to write your own version of SequenceEqual , like this: 编辑 :在.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;
}

You could write it to take IEnumerable<T> instead of IList<T> , but it'd be somewhat slower because it wouldn't be able to exit early if the parameters have different sizes. 您可以将其编写为使用IEnumerable<T>而不是IList<T> ,但是它会稍慢一些,因为如果参数的大小不同,它将无法提早退出。

It is really important to make sure you keep the override of .GetHashCode() in step with .Equals(). 以确保您保持.GetHashCode()的覆盖步骤与.Equals这是非常重要的()。

Basically, you must make sure they consider the same fields so as not to violate the first of the three rules of GetHashCode (from MSDN object.GetHashCode() ) 基本上,必须确保它们考虑相同的字段,以免违反GetHashCode的三个规则中的第一个规则(来自MSDN object.GetHashCode()

If two objects compare as equal, the GetHashCode method for each object must return the same value. 如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。 However, if two objects do not compare as equal, the GetHashCode methods for the two object do not have to return different values. 但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值。

In other words, you must make sure that every time .Equals considers two instances equal, they will also have the same .GetHashCode(). 换句话说,必须确保每次.Equals都认为两个实例相等时,它们也将具有相同的.GetHashCode()。

As mentioned by someone else here, this question details a good implementation. 就像其他人在这里提到的那样, 这个问题详述了一个好的实现。 In case you are interested, I wrote up a few blog articles on investigating hash codes early last year. 如果您有兴趣,我在去年年初写了一些博客文章来研究哈希码。 You can find my ramblings here (the first blog entry I wrote on the subject) 您可以在这里找到我的文章(我写的第一篇博客文章)

There's a good discussion of the issues here , and the most recent update refers to the BaseObject abstract class provided by SharpArchitecture. 还有的问题商量好了这里 ,和最新的更新是指BaseObject抽象类的SharpArchitecture提供。

If you want something more ad hoc , I've found that the code that ReSharper generates for Equals() and GetHashCode() is fine. 如果您需要更多临时信息 ,我发现ReSharper为Equals()和GetHashCode()生成的代码很好。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM