在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() ;
}
或者我应该做些什么?
答案 0 :(得分:12)
System.Array
不会覆盖GetHashCode
或Equals
,因此它们使用引用相等性。因此,你不应该打电话给他们。
要实施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
方法,这是非常容易使用和高效的。