默认实现如何GetHashCode()工作?它是否有效且足够好地处理结构,类,数组等?
我试图决定在什么情况下我应该自己打包,在什么情况下我可以安全地依赖默认实现来做好.如果可能的话,我不想重新发明轮子.
根据MSDN,散列函数必须具有以下属性:
如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值.但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值.
只要没有对对象状态的修改来确定对象的Equals方法的返回值,对象的GetHashCode方法必须始终返回相同的哈希代码.请注意,这仅适用于当前应用程序的执行,并且如果再次运行应用程序,则可以返回不同的哈希代码.
为获得最佳性能,哈希函数必须为所有输入生成随机分布.
我一直在以下场景中找到自己:我创建了一个类,实现IEquatable<T>并重写了object.Equals(object).MSDN声明:
重写Equals的类型也必须覆盖GetHashCode; 否则,Hashtable可能无法正常工作.
然后它通常会为我停止一点.因为,你如何正确覆盖object.GetHashCode()?从来没有真正知道从哪里开始,这似乎是很多陷阱.
在StackOverflow中,有很多与GetHashCode重写相关的问题,但大多数问题似乎都是针对非常特殊的情况和具体问题.因此,我想在这里得到一个很好的汇编.概述与一般建议和指南.该做什么,不该做什么,常见的陷阱,从哪里开始,等等.
我希望它特别针对C#,但我认为它对其他.NET语言也有同样的作用(?).
我想也许最好的方法是每个主题创建一个答案,首先是快速简短的答案(如果可能的话,尽可能接近单行),然后可能会有更多信息,并以相关问题,讨论,博客文章等结束. ,如果有的话.然后,我可以创建一个帖子作为接受的答案(将其置于顶部),只需一个"目录".尽量保持简洁明了.而且不要只链接到其他问题和博客文章.尝试采用它们的本质,然后链接到源(特别是因为源可能会消失.另外,请尝试编辑和改进答案,而不是创建许多非常相似的答案.
我不是一个非常优秀的技术作家,但我至少会尝试格式化答案,使它们看起来很相似,创建目录等.我也会尝试在这里搜索一些相关的问题来回答部分问题.这些并且可能拉出我能管理的那些的本质.但由于我在这个主题上不是很稳定,所以我会尽量远离这个主题:p
在阅读StackOverflow上有关覆盖的所有问题和答案之后,GetHashCode()我编写了以下扩展方法,以便轻松方便地覆盖GetHashCode():
public static class ObjectExtensions
{
private const int _seedPrimeNumber = 691;
private const int _fieldPrimeNumber = 397;
public static int GetHashCodeFromFields(this object obj, params object[] fields) {
unchecked { //unchecked to prevent throwing overflow exception
int hashCode = _seedPrimeNumber;
for (int i = 0; i < fields.Length; i++)
if (fields[i] != null)
hashCode *= _fieldPrimeNumber + fields[i].GetHashCode();
return hashCode;
}
}
}
Run Code Online (Sandbox Code Playgroud)
(我基本上只重构了有人在那里发布的代码,因为我真的很喜欢它可以一般使用)
我用的是这样的:
public override int GetHashCode() {
return this.GetHashCodeFromFields(field1, field2, field3);
}
Run Code Online (Sandbox Code Playgroud)
你看到这段代码有什么问题吗?