MSDN文档中关于Object.GetHashCode()的描述有三条相互矛盾的规则。
- 如果两个相同类型的对象表示相同的值,则哈希函数必须为任一对象返回相同的常量值。
- 为了获得最佳性能,哈希函数必须为所有输入生成随机分布。
- 无论对对象进行了哪些更改,哈希函数都必须返回完全相同的值。
规则1和3对我来说是相互矛盾的。
Object.GetHashCode()返回基于对象的值还是引用的唯一数字。如果我重写该方法,我可以选择使用什么,但如果有人知道内部使用了什么,我想知道。
MSDN文档中关于Object.GetHashCode()的描述有三条相互矛盾的规则。
规则1和3对我来说是相互矛盾的。
Object.GetHashCode()返回基于对象的值还是引用的唯一数字。如果我重写该方法,我可以选择使用什么,但如果有人知道内部使用了什么,我想知道。
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方法不必返回不同的值。
对象的GetHashCode方法必须在决定对象的Equals方法的返回值的对象状态没有修改的情况下始终返回相同的哈希代码。请注意,这仅对应用程序的当前执行有效,在再次运行应用程序时可以返回不同的哈希代码。
为获得最佳性能,哈希函数必须为所有输入生成随机分布。
如果您提到的是第二个要点,则关键短语是“只要对象状态没有修改”和“仅对应用程序的当前执行有效”。
此外,根据文档,
一个哈希函数用于快速生成与对象值对应的数字(哈希码)。哈希函数通常针对每个类型进行特定设计,并且必须至少使用一个实例字段作为输入。关于实际实现,它明确说明派生类只有在定义值相等性为引用相等性且类型不是值类型时才能推迟到Object.GetHashCode实现。换句话说,由于没有真正的实例字段可用,因此Object.GetHashCode的默认实现将基于引用相等性,并且不能保证不同对象返回唯一的返回值。否则,您的实现应该特定于您的类型,并且应该使用至少一个实例字段。例如,String.GetHashCode的实现返回相同的哈希码以表示相同的字符串值,因此如果两个String对象表示相同的字符串值,则它们将返回相同的哈希码,并使用字符串中的所有字符生成该哈希值。规则1和3并不真正矛盾。
对于引用类型,哈希码是从对象的引用派生出来的 - 更改对象的属性,引用仍然相同。
对于值类型,哈希码是从值派生出来的,更改值类型的属性会得到完全新的值类型实例。
GetHashCode
(超出Microsoft规则)的方法方面,Eric Lipperts(C#的联合设计师)的博客文章“Guidelines and rules for GetHashCode”提供了非常好的解释。这里不推荐添加超链接(因为它们可能会失效),但这个链接非常值得一看。如果链接丢失,根据上面提供的信息,也可以找到它。我无法确定在真正的.NET Framework中如何实现Object.GetHashCode,但在Rotor中,它使用SyncBlock索引作为哈希码。有一些关于此的博客文章在网上,但大多数都是来自2005年。
默认情况下,它是基于对象的引用来进行操作的,但这意味着它是完全相同的对象,因此两者将返回相同的哈希值。但哈希应该基于值,就像字符串类的情况一样。"a"和"b"将具有不同的哈希值,但"a"和"a"将返回相同的哈希值。
GetHashCode
是Object
基类的一个方法,这只是 C# 语言中一个糟糕的设计决策。此外,我的回答并不是说你必须使每个哈希表键类型都是不可变的——仅仅是这样做会有很大的帮助。 - Konrad Rudolph^
符号? - Farhad ZamaniHashCode.Combine
,但是(如果我没记错的话)当我写这个答案时还没有可用。 - Konrad Rudolph