.NET程序员都知道,如果我们重写一个类的Equals方法而没有重写GetHashCode,则VS会提示警告 :“***”重写 Object.Equals(object o)但不重写 Object.GetHashCode() 。

但是,为什么重写Equals一定要同时重写GetHashCode呢?

微软的解释是:

GetHashCode 基于适合哈希算法和诸如哈希表的数据结构的当前实例返回一个值。 两个相等的同类型对象必须返回相同的哈希代码,才能确保以下类型的实例正确运行:

链接: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

如果我的文章对你有帮助,就点一下推荐吧.(*^__^*)
 
 
标签: .NET
好文要顶 关注我 收藏该文  
4
0
 
 
 
posted @ 2013-08-12 22:49 Gyoung 阅读(2608) 评论(4) 编辑 收藏
 
评论列表
 

#1楼 2013-08-13 09:03 害怕飞的鸟 

但是自己写这个函数的时候貌似还得注意hash碰撞的问题。。。否则。。。容易出现哈希碰撞拒绝服务攻击。。。

【转】重写Equals为什么要同时重写GetHashCode的更多相关文章

  1. 重写Equals为什么要同时重写GetHashCode

    .NET程序员都知道,如果我们重写一个类的Equals方法而没有重写GetHashCode,则VS会提示警告 :“***”重写 Object.Equals(object o)但不重写 Object.G ...

  2. java -为什么重写equals(),还需要重写hashCode()?

    1.先post这两个方法的基本定义: equals()的定义: 浅谈Java中的equals和==(转) hashCode()的定义: java中hashCode()方法的作用 Java中hashCo ...

  3. 为什么重写equals()方法就必须重写hashCode()方法

    hashCode()和equals()保持一致,如果equals方法返回true,那么两个对象的hasCode()返回值必须一样.如果equals方法返回false,hashcode可以不一样,但是这 ...

  4. 一文搞懂--Java中重写equals方法为什么要重写hashcode方法?

    Java中重写equals方法为什么要重写hashcode方法? 直接看下面的例子: 首先我们只重写equals()方法 public class Test { public static void ...

  5. 为什么重写equals的同时要重写hashcode

    在覆盖equals方法的时候,你必须要遵守它的通用约定.下面是约定的内容,来自Object的规范[JavaSE6] 自反性.对于任何非null的引用值x,x.equals(x)必须返回true. 对称 ...

  6. 重写equals()方法也要重写hashcode()方法

    如果我们对equals方法进行了重写,建议一定要对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值.

  7. JAVA中重写equals()方法为什么要重写hashcode()方法?

    object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...

  8. why在重写equals时还必须重写hashcode方法

    首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法 public boolean equals(Object anO ...

  9. 为什么重写equals时一定要重写hashcode

    我们开发时写一个类,默认继承Object类,Object类的equals方法是比较是否指向同一个对象(地址是否相同), Object类 的hashcode方法返回的对象内存地址的值, 一个类只重写了e ...

随机推荐

  1. Java使用Jedis操作Redis大全

    Java操作Redis需要导入两个jar: commons-pool2-2.4.2.jar jedis-2.1.0.jar package com.chinasofti.test; import ja ...

  2. 国内最全的Spring Boot系列之二

    历史文章 <国内最全的Spring Boot系列之一> 视频&交流平台 SpringBoot视频:http://t.cn/R3QepWG Spring Cloud视频:http:/ ...

  3. 树莓派(Raspberry Pi 3)安装centos7后yum无法使用解决办法

    树莓派(Raspberry Pi 3)安装centos7后yum无法使用解决办法 人穷,闲鱼淘了个二手的树莓派3 英国版,无奈咱也不会用,很无奈~ 安装教程百度到的差不多都可以,找个格式正常的一步一步 ...

  4. Vue stage3

    <body> <div id="box1"> <div v-bind:class="{ 'active': isActive, 'error ...

  5. mybatis学习 -每天一记 通用mapper 关于UUID回显的配置

    在使用通用mapper插入数据UUID回显 在使用通用mapper插入数据时,发现主键没有回显,我这里的主键是UUID的,解决方案是:配置一个MapperScannerConfigurer. @Bea ...

  6. FPGA——流水灯(一)

    对于FPGA的结构原理,先不进行全面的了解,先能根据教程程序看得懂,写得出来跑起来.慢慢的了解程序运行的原理,各种语法的使用. 今天对流水的程序有一个认识,熟悉软件的使用,语法规则,原理.以正点原子的 ...

  7. ajax的4个字母分别是什么意思

    Asynchronous JavaScript and XML 的缩写,异步的JavaScript和XML.在不重新加载整个页面的情况下 ,AJAX 与服务器交换数据并更新部分网页.

  8. Python module ---- os

    os 模块Python标准库中的一个用于访问操作系统功能的模块,使用OS模块中提供的接口,可以实现跨平台访问.提供了一个统一的操作系统接口函数, 这些接口函数通常是平台指定的,os 模块能在不同操作系 ...

  9. 尚硅谷springboot学习35-启动原理

    先列出几个重要的事件回调机制 配置在META-INF/spring.factories ApplicationContextInitializer SpringApplicationRunListen ...

  10. spring中Constructor、@Autowired、@PostConstruct的顺序

    其实从依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入.所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入 ...