必须重写这两个方法

时间:2022-05-29 08:25:30

首先先谈一下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却不一样,我们可以简单的理解为是coor1与coor2的内存地点差别,所以CLR认为它们是不一样的。

Ps:在措施的生命周期中,不异的东西、变量返回的HashCode是不异的,并且是独一的。但是绝对不允许做长期性存储,措施一旦结束并从头启动后,同样的东西无法获得上次措施运行时的HashCode。

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

其实在上面的两个东西中(coor1、coor2),coor1.Equals(coor2)的返回功效为false(因为内存地点差别),如果我们想让它们的返回功效为true的话,只能重写Equals要领(如下图)。

必须重写这两个方法

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

代码段一、二:

必须重写这两个方法

代码段三:

必须重写这两个方法

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

固然,如果你没筹算在代码中使用Dictionary或HashTable就无所谓写不写了,换句话说,如果要把引用类型做为Dictionary或HashTable的key使用时,必需重写这两个要领。

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

好了,说了这么多你应该对这两个要领有了从头的认识了吧。如果还是不大白的话,用代码实现一下,保准大白。