博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Equals()和GetHashCode()方法深入了解
阅读量:4881 次
发布时间:2019-06-11

本文共 1946 字,大约阅读时间需要 6 分钟。

最近在看Jeffrey RichterCLR Via C#,在看到GetHashCode()方法的时候,有一个地方不是特别明白,就是重写Equals()方法时为什么要把GetHashCode()方法一块重写(不重写也没关系,但是微软会发送一条警告)。在解释这个问题之前需要先把Equals()GetHashCode()方法进行深入了解。

 

首先先谈一下Equals()这个方法:

Equals()方法,来自于Object,是我们经常需要重写的方法。此方法的默认实现大概是这样的:

public virtual bool Equals(object obj){  if(obj==null) return false;   if(GetType() != obj.GetType()) return false;   Return true; }

 

由此可以看出,默认的实现其实比较的是两个对象的内存地址(==操作符默认比较内存地址)。值类型和string类型除外,因为所有值类型继承于System.ValueType()(System.ValueType()同样继承于Object,但是System.ValueType()本身却是引用类型),而System.ValueType()Equals()==操作符进行了重写,是逐字节比较的。而string类型是比较特殊的引用类型,所以strIng在很多地方都是特殊处理的,此处就不做深究了。

Ps:按Jeffrey Richter的说法,在值类型使用Equals()时,因为Equals()使用了反射,在比较时会影响效率。

说完Equals()后再来聊一聊GetHashCode()

其实GetHashCode()在操作值类型的时候也是被System.ValueType()重写的。经过楼主测试的几个常用值类型来看,值类型的GetHashCode()基本都是原值输出(特指整数,Int32除外),真实性有待验证。结果如下:

说完值类型,说一下引用类型,先看下面这张运行结果:

从上图的结果可以看出,虽然string是引用类型,但是只要值一样,返回的HashCode也是一样的,这取决于它的特殊性。而我们自己写的类型Coordinates同样的值但返回的HashCode却不一样,我们可以简单的理解为是coor1coor2的内存地址不同,所以CLR认为它们是不一样的。

Ps:在程序的生命周期中,相同的对象、变量返回的HashCode是相同的,并且是唯一的。但是绝对不允许做持久性存储,程序一旦结束并重新启动后,同样的对象无法获得上次程序运行时的HashCode

了解了两个方法后,开始今天的重点话题。

其实在上面的两个对象中(coor1coor2)coor1.Equals(coor2)的返回结果为false(因为内存地址不同),如果我们想让它们的返回结果为true的话,只能重写Equals方法(如下图)

重点来了,重写完Equals以后,vs发出了警告,虽然程序猿从来都是无视警告的,但这个警告确实有必要了解一下,先来看下面这三段代码。

代码段一、二:

 

代码段三:

看完这三段代码,应该就理解为什么要重写Equal时有必要重写GetHashCode了。

当然,如果你没打算在代码中使用DictionaryHashTable就无所谓写不写了,换句话说,如果要把引用类型做为DictionaryHashTablekey使用时,必须重写这两个方法。

原因:当我们把引用类型(string除外)做为DictionaryHashTablekey时,有可能永远无法根据Key获得value的值,或者说两个类型的HashCode永远不会相等。就拿Dictionary来说,虽然我们存储的时候是键值对,但是CLR会先把key转成HashCode并且验证Equals后再做存储,根据key取值的时候也是把key转换成HashCode并且验证Equals后再取值,一定要注意验证时HashCodeEquals的关系是并且(&&)的关系。也就是说,只要GetHashCodeEqulas中有一个方法没有重写,在验证时没有重写的那个方法会调用基类的默认实现,而这两个方法的默认实现都是根据内存地址判断的,也就是说,其实一个方法的返回值永远会是false。其结果就是,存储的时候你可能任性的存,在取值的时候就是你哭着找不着娘了。

好了,说了这么多你应该对这两个方法有了重新的认识了吧。如果还是不明白的话,用代码实现一下,保准明白。

转载于:https://www.cnblogs.com/zhengwei-cq/p/8316303.html

你可能感兴趣的文章
九度oj 1006
查看>>
HDU6400-2018ACM暑假多校联合训练1004-Parentheses Matrix-构造
查看>>
最短路问题专题
查看>>
《Redis复制与可扩展集群搭建》看后感
查看>>
Jquery Mobile总结
查看>>
223. Rectangle Area
查看>>
spring boot + velocity中文乱码解决方式
查看>>
读罢泪两行,人生成长必须面对的10个残酷事实
查看>>
ASP 32位程序运行与64位问题:ADODB.Connection 错误 '800a0ea9' 未指定提供程序,也没有指派的默认提供程序。...
查看>>
xcode-git笔记
查看>>
TCP和UDP的优缺点及区别
查看>>
MATLAB消除曲线毛刺Outlier Detection and Removal [hampel]
查看>>
MySQL DATE_SUB() 函数
查看>>
在SSH框架下按条件分页查询
查看>>
jquery选择器
查看>>
【javascript学习——《javascript高级程序设计》笔记】DOM操作
查看>>
高效的SQL语句翻页代码
查看>>
NPAPI插件开发详细记录:用VS2010开发NPAPI插件步骤
查看>>
linux下Makefile全解(二)
查看>>
XMLHTTP.readyState的五种状态
查看>>