编辑:System.HashCode
现已发布。现在推荐使用以下方法创建哈希码:
public override int GetHashCode()
{
return HashCode.Combine(fieldA, fieldB, fieldC);
}
System.HashCode.Combine()
在内部调用每个字段的 .GetHashCode()
,并自动完成正确的操作。
对于非常多的字段(超过8个),您可以创建一个 HashCode
实例,然后使用 .Add()
方法:
public override int GetHashCode()
{
HashCode hash = new HashCode();
hash.Add(fieldA);
hash.Add(fieldB);
hash.Add(fieldC);
hash.Add(fieldD);
hash.Add(fieldE);
hash.Add(fieldF);
hash.Add(fieldG);
hash.Add(fieldH);
hash.Add(fieldI);
return hash.ToHashCode();
}
Visual Studio 2019现在有一个快速操作助手来为你生成Equals()
和GetHashCode()
。只需右键单击声明中的类名> 快速操作和重构> 生成Equals和GetHashCode。选择要用于相等性的成员,还要“实现IEquatable”,然后单击确定。
最后一件事:如果您需要获取对象的结构哈希码,例如如果您想要包括基于其内容(即结构)而不是引用更改的数组的哈希码,则需要将字段强制转换为IStructuralEquatable
并手动获取其哈希码,如下所示:
public override int GetHashCode()
{
return HashCode.Combine(
fieldA,
((IStructuralEquatable)stringArrayFieldB).GetHashCode(EqualityComparer<string>.Default));
}
这是因为几乎总是显式实现了
IStructuralEquatable
接口,所以需要将其转换为
IStructuralEquatable
才能调用
IStructuralEquatable.GetHashCode()
方法,而不是默认的
object.GetHashCode()
方法。
最后,在当前实现中,
int
的
.GetHashCode
只是整数值本身,因此将哈希码值传递给
HashCode.Combine()
而不是字段本身对结果没有影响。
旧答案:
为了完整起见,这里提供了来自
.NET Tuple参考源代码第52行的哈希算法。有趣的是,这个哈希算法是从
System.Web.Util.HashCodeCombiner
复制过来的。
以下是代码:
public override int GetHashCode() {
return CombineHashCodes(this.item1.GetHashCode(), this.item2.GetHashCode(), this.item3.GetHashCode());
}
internal static int CombineHashCodes(int h1, int h2) {
return (((h1 << 5) + h1) ^ h2);
}
internal static int CombineHashCodes(int h1, int h2, int h3) {
return CombineHashCodes(CombineHashCodes(h1, h2), h3);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4) {
return CombineHashCodes(CombineHashCodes(h1, h2), CombineHashCodes(h3, h4));
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5) {
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), h5);
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6) {
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6));
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7) {
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7));
}
internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8) {
return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7, h8));
}
当然了,实际上元组 GetHashCode()
(实际上是一个 Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
)有一个大的 switch
块来决定调用哪一个,基于它持有多少项 - 您自己的代码可能不需要这样。
GetHashCode()
方法,如果你想合并它们,只需将任何逻辑放入帮助方法即可。 - evanmcdonnalEquals()
方法需要有充分的理由。 - Federico Berasategui