Object.GetHashCode()上的MSDN文档描述了该方法应该如何工作的3个矛盾规则.
如果两个相同类型的对象表示相同的值,则哈希函数必须为任一对象返回相同的常量值.
为获得最佳性能,哈希函数必须为所有输入生成随机分布.
无论对对象做出任何更改,哈希函数都必须返回完全相同的值.
规则1和3与我相矛盾.
Object.GetHashCode()是否根据对象的值或对象的引用返回唯一的数字.如果我覆盖方法,我可以选择使用什么,但我想知道内部使用的内容,如果有人知道的话.
规则1和3与我相矛盾.
在某种程度上,他们是.原因很简单:如果对象存储在哈希表中,并且通过更改其值,您更改其哈希值,则哈希表已丢失该值,并且您无法通过查询哈希表再次找到它.重要的是,当对象存储在哈希表中时,它们保留其哈希值.
为了实现这一点,通常最简单的方法是使可清洗对象不可变,从而避免整个问题.但是,只有那些确定哈希值的字段是不可变的就足够了.
请考虑以下示例:
struct Person { public readonly string FirstName; public readonly string Name; public readonly DateTime Birthday; public int ShoeSize; }
人们很少改变他们的生日,大多数人从不改变他们的名字(除非结婚).然而,他们的鞋子尺寸可能会随意增长,甚至会缩小.因此,使用他们的生日和名字而不是他们的鞋子大小来识别人是合理的.哈希值应该反映这一点:
public int GetHashCode() { return FirstName.GetHashCode() ^ Name.GetHashCode() ^ Birthday.GetHashCode(); }
不确定您所指的MSDN文档.查看Object.GetHashCode(http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx)上的当前文档提供了以下"规则":
如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值.但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值.
只要没有对对象状态的修改来确定对象的Equals方法的返回值,对象的GetHashCode方法必须始终返回相同的哈希代码.请注意,这仅适用于当前应用程序的执行,并且如果再次运行应用程序,则可以返回不同的哈希代码.
为获得最佳性能,哈希函数必须为所有输入生成随机分布.
如果您指的是第二个项目符号点,则此处的关键短语是"只要对象状态没有修改","仅对应用程序的当前执行为真".
另外从文档中,
哈希函数用于快速生成对应于对象值的数字(哈希码).散列函数通常特定于每个类型,并且必须至少使用一个实例字段作为输入.[ 重点补充是我的.]
至于实际实现,它明确指出派生类可以推迟到Object.GetHashCode实现当且仅当派生类将值相等定义为引用相等,类型不是值类型.换句话说,Object.GetHashCode的默认实现将基于引用相等,因为不存在要使用的实例字段,因此不保证不同对象的唯一返回值.否则,您的实现应该特定于您的类型,并且应该至少使用一个实例字段.例如,String.GetHashCode的实现为相同的字符串值返回相同的哈希码,因此如果两个String对象表示相同的字符串值,则返回相同的哈希码,并使用字符串中的所有字符生成该哈希值.