C# 为什么不';在个人类上使用字典时,我是否必须重写GetHashCode?
它似乎总是“工作”而不必做任何事情 我唯一能想到的是,每个类都有一个隐藏的静态标识符,C# 为什么不';在个人类上使用字典时,我是否必须重写GetHashCode?,c#,hash,dictionary,hashtable,C#,Hash,Dictionary,Hashtable,它似乎总是“工作”而不必做任何事情 我唯一能想到的是,每个类都有一个隐藏的静态标识符,Object.GetHashCode使用它。(还有,有人知道Object.GetHashCode是如何实现的吗?我在.NET Reflector中找不到它) 我从来没有重写过GetHashCode,但我一直在阅读,人们说,只有在重写Equals并为应用程序提供自定义的相等检查时,才需要这样做,所以我想我没事吧 我仍然想知道这个魔法是如何工作的,不过,=pObject的Equals()和GetHashCode()
Object.GetHashCode
使用它。(还有,有人知道Object.GetHashCode是如何实现的吗?我在.NET Reflector中找不到它)
我从来没有重写过GetHashCode
,但我一直在阅读,人们说,只有在重写Equals并为应用程序提供自定义的相等检查时,才需要这样做,所以我想我没事吧
我仍然想知道这个魔法是如何工作的,不过,=p
Object
的Equals()
和GetHashCode()
(您继承的)的实现通过引用进行比较。Object.GetHashCode
在本机代码中实现;您可以在SSCLI(转子)中看到它
一个类的两个不同实例(通常)具有不同的哈希代码,即使它们的属性相等
如果要按值进行比较,您只需覆盖它们—如果要将具有相同属性的不同实例进行相等比较。这实际上取决于您对相等的定义
class Person
{
public string Name {get; set;}
}
void Test()
{
var joe1 = new Person {Name="Joe"};
var joe2 = new Person {Name="Joe"};
Assert.AreNotEqual(joe1, joe2);
}
如果对相等有不同的定义,则应重写
Equals
&GetHashCode
,以获得适当的行为。是否将自定义类用作键或值?如果只对值使用它们,那么它们的GetHashCode
就无关紧要了
如果将它们用作键,则哈希的质量会影响性能。字典
存储每个哈希代码的元素列表,因为哈希代码不需要是唯一的。在最坏的情况下,如果所有键都具有相同的哈希代码,那么字典的查找时间将类似于列表O(n),而不是哈希表O(1)
Object.GetHashCode的文档非常简单:
GetHashCode方法的默认实现不保证不同对象的唯一返回值。。。因此,此方法的默认实现不得用作哈希目的的唯一对象标识符
它似乎总是“工作”而不必做任何事情
您没有告诉我们您的键使用的是值类型还是引用类型
如果您使用的是值类型,Equals
和GetHashCode
的默认实现是正常的(Equals
检查字段是否相等,GetHashCode
基于字段(不一定是所有字段!))。如果您使用的是引用类型,Equals
和GetHashCode
的默认实现使用引用相等,这可能没问题,也可能没问题;这取决于你在做什么
我唯一能想到的是,每个类都有一个隐藏的静态标识符,Object.GetHashCode
使用它
否。默认值是基于值类型字段和引用类型引用的哈希代码
(还有,有人知道Object.GetHashCode是如何实现的吗?我在.NET Reflector中找不到它)
这是一个实现细节,您永远不应该需要知道,也永远不应该依赖它。你随时都可能改变
我从来没有重写过GetHashCode,但我一直在阅读,人们说,只有在重写Equals并为应用程序提供自定义的相等检查时,才需要重写GetHashCode,所以我想我没事吧
那么,默认平等对你合适吗?如果不是,则为您的T
重写equalitycomparer
和GetHashCode
或执行IEqualityComparer
不过,我还是想知道魔法是如何发挥作用的
每个对象都有等于
和GetHashCode
。默认实现如下所示:
Equals
表示值相等Equals
表示引用相等GetHashCode
基于字段(同样,不一定是所有字段!)GetHashCode
基于引用Dictionary
构造函数的重载没有为t
使用IEqualityComparer
,它将使用EqualityComparer.Default
。这个IEqualityComparer
只使用等于和GetHashCode
。因此,如果您没有覆盖它们,那么您将得到上面定义的实现。如果覆盖Equals
和GetHashCode
则这就是EqualityComparer。默认值将使用
否则,将IEqualityComparer
的自定义实现传递给Dictionary
的构造函数哈希代码用于优化哈希表(字典)中的查找性能。虽然哈希代码的目标是尽可能减少对象实例之间的冲突,但不能保证它们是唯一的。目标应该是在给定一组典型类型的对象的int范围内均匀分布
哈希表的工作方式是每个对象实现一个函数来计算哈希代码,希望尽可能分布在int范围内。两个不同的对象可以生成相同的哈希代码,但给定对象数据的对象实例应始终生成相同的哈希代码。因此,它们不是唯一的,不应用于平等。哈希表分配一个大小为n(远小于int范围)的数组,当一个对象被添加到哈希表中时,它调用GetHashCode,然后根据分配的数组大小调整它的mod'd(%)。对于表中的碰撞,通常会链接对象列表。由于计算哈希代码应该非常快,所以查找是快速跳转到数组