【转】重写Equals为什么要同时重写GetHashCode
.NET程序员都知道,如果我们重写一个类的Equals方法而没有重写GetHashCode,则VS会提示警告 :“***”重写 Object.Equals(object o)但不重写 Object.GetHashCode() 。
但是,为什么重写Equals一定要同时重写GetHashCode呢?
微软的解释是:
GetHashCode 基于适合哈希算法和诸如哈希表的数据结构的当前实例返回一个值。 两个相等的同类型对象必须返回相同的哈希代码,才能确保以下类型的实例正确运行:
HashTable
Dictionary
SortDictionary
SortList
HybredDictionary
实现 IEqualityComparer 的类型
链接:http://msdn.microsoft.com/zh-cn/library/vstudio/ms182358.aspx
举个例子:
重写一个Person类

public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; } /// <summary>
/// 重写Equals,如果Name与Age相等,就认为类相等
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (obj is Person)
{
var person = obj as Person;
return person.Age == this.Age && person.Name == this.Name;
}
else
return false;
}
}

写一个测试方法:

public static void Main(string[] args)
{
Person person1 = new Person() { Id = 1, Name = "AA", Age = 21 };
Person person2 = new Person() { Id = 2, Name = "AA", Age = 21 }; Console.WriteLine("person1与person2是否相等:" + person1.Equals(person2));
Console.Read();
}

结果:

返回的结果是true,这好像是我们的重写方法成功了。那我们继续写一个测试方法吧。
ICollection<Person> list = new HashSet<Person>();
list.Add(person1);
Console.WriteLine("List是否包含person1:"+list.Contains(person1));
Console.WriteLine("List是否包含person2:" + list.Contains(person2));
结果:

这时,就出问题了。既然person1与person2相等,list它包含person1,那也应该包含person2吧。原因就是我们没有重写GetHashCode方法,相同的对象没有返回相等的HashCode。
我们重新改变一下Person,让它重写GetHashCode方法。

public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; } /// <summary>
/// 重写Equals,如果Name与Age相等,就认为类相等
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (obj is Person)
{
var person = obj as Person;
return person.Age == this.Age && person.Name == this.Name;
}
else
return false;
} public override int GetHashCode()
{
return this.Name.GetHashCode()^this.Age.GetHashCode();
}
}

再运行两个测试方法:

现在,方法都返回true了。
还有一个例子,如果将Person类当作键值放在字典中也会有问题,可以参见:http://book.51cto.com/art/201109/292340.htm。
重写GetHashCode的原则很简单,只要能保证两个相等的同类型对象返回相同的哈希代码就OK了。
还找到一个说得比较好的地方,里面第二个评论很精彩。http://blog.csdn.net/chenyuxu0/article/details/5886771
【转】重写Equals为什么要同时重写GetHashCode的更多相关文章
- 重写Equals为什么要同时重写GetHashCode
.NET程序员都知道,如果我们重写一个类的Equals方法而没有重写GetHashCode,则VS会提示警告 :“***”重写 Object.Equals(object o)但不重写 Object.G ...
- java -为什么重写equals(),还需要重写hashCode()?
1.先post这两个方法的基本定义: equals()的定义: 浅谈Java中的equals和==(转) hashCode()的定义: java中hashCode()方法的作用 Java中hashCo ...
- 为什么重写equals()方法就必须重写hashCode()方法
hashCode()和equals()保持一致,如果equals方法返回true,那么两个对象的hasCode()返回值必须一样.如果equals方法返回false,hashcode可以不一样,但是这 ...
- 一文搞懂--Java中重写equals方法为什么要重写hashcode方法?
Java中重写equals方法为什么要重写hashcode方法? 直接看下面的例子: 首先我们只重写equals()方法 public class Test { public static void ...
- 为什么重写equals的同时要重写hashcode
在覆盖equals方法的时候,你必须要遵守它的通用约定.下面是约定的内容,来自Object的规范[JavaSE6] 自反性.对于任何非null的引用值x,x.equals(x)必须返回true. 对称 ...
- 重写equals()方法也要重写hashcode()方法
如果我们对equals方法进行了重写,建议一定要对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值.
- JAVA中重写equals()方法为什么要重写hashcode()方法?
object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...
- why在重写equals时还必须重写hashcode方法
首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法 public boolean equals(Object anO ...
- 为什么重写equals时一定要重写hashcode
我们开发时写一个类,默认继承Object类,Object类的equals方法是比较是否指向同一个对象(地址是否相同), Object类 的hashcode方法返回的对象内存地址的值, 一个类只重写了e ...
随机推荐
- 傻瓜学编程之block_2
block的实质 以一个简单的实现为列子: - (void)myBlcokTest{ void (^blk)()=^{ printf(@“beijinghuanyingni”); }; blk(); ...
- TopSnackbar,在顶部滑出显示的Snackbar;
TopSnackbar 既然你能找到这篇文章,说明你一定使用过或了解Snackbar,所以我就不介绍Snackbar了.嗯~有图有真相! 嗯,就是图上这样: 我把Snackbar的源码拉了过来,重写了 ...
- OGG-01091 Unable to open file "./dirdat/cs001481" (error 2, No such file or directory)
记一次ogg报错ogg-01091的处理过程 现场有一套RAC数据库的服务器异常重启,其中一个节点上部署了OGG,机器开机之后,发现OGG所有应用进程abended状态,查看日志,发现报错如下图: 分 ...
- cd tom-bash: cannot create temp file for here-document: No space left on device
Linux使用tab补全时提示 cd tom-bash: cannot create temp file for here-document: No space left on device 这是因为 ...
- Linux 修改zabbix server的web访问端口
在安装zabbix server的时候默认就安装了apache,zabbix依靠apache提供的web服务,修改Zabbix的浏览器访问端口,就是修改apache的服务端口(默认端口:80) 1.编 ...
- CentOS使用nginx部署https服务
nginx安装参考:https://www.cnblogs.com/taiyonghai/p/6728707.html 自签证书生成参考:https://gmd20.github.io/blog/op ...
- Flask框架里的cookie和session
# -*- encoding: utf-8 -*- #cookie 相关的操作,依赖与make_response库,调用cookie依赖request模块 from flask import Flas ...
- Python初学(1)
最近在学习python,以后想编写一些工作中用的到的脚本.python的入门我选择了<python从初学到入门>,这篇文章我会跟进我的学习进度.算是一个笔记吧. 我本身是熟悉C语言的,看p ...
- Mysql 创建用户授权
MySQL创建用户与授权 一. 创建用户 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明: username:你将创建的用 ...
- 循环队列搜索 Search in Rotated Sorted Array
这里比较重要的是,不要一上来就判断mid 和 target有没有关系.因为数组是无序的,这样的判断毫无结论,只会搞的更复杂.应该先想办法判断出哪一侧是有序的. class Solution { pub ...
