在日常开发中经常需要编写代码比较不同的对象。例如,有时需要将对象都放到一个集合中,并编写代码对集合中的对象进行排序、搜索或者比较。

System.Object类有两个Equals方法,如下:

1、实例Equals方法(可重写),代码如下:

public virtual bool equals(object obj) => RuntimeHelpers.Equals(this, obj)

再看看RuntimeHelpers.Equlas里面调的是什么方法,代码如下:

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public static extern bool Equals(object o1, object o2);

ok,这里的extern关键字告诉你,接下来的不用你考虑了!

2、静态方法Equals方法,代码如下:

public static bool Equals(object objA,object objB)=>
((objA==objB) || (((objA!=null) && (objB!=null)) && objA.Equals(objB)))

继续深入解析代码,发现objA.Equals调用了上面的实例Equals方法.其实就是在实例Equals方法的基础上做了非空判断.然后方法做了静态化.

到这里源码解析完毕,由于到extern这一步解析不下去了(博主实力有限),如有知道的请告知!万分感谢!

由于类型能够重写Equals方法,所以Equals方法的逻辑远比想象的要复杂.下面来举几个例子:

1、由于类型能够重写Equals方法,所以不能使用它来测试同一性,为了解决这个问题,Object类型提供了ReferenceEquals方法来比较两个对象的同一性,ReferenceEquals代码如下:

public static bool ReferenceEquals(object objA,object objB)=>(objA==objB)

注:判断两个对象的"同一性"不应该使用C#的==操作符(除非将两个操作符进行装箱转换为Object),因为某个操作数可能重载了==操作符

2、System.ValueType(所有值类型的基类)就重写了Object的Equals方法,并对两个对象进行了正确的值相等检查而不是同一性检查.代码如下:

public bool Equals(uint obj)=>(this == obj);

==操作符进行的值检查.

ValueType.Equals内部会进行一下操作:

1、如果obj实参为null,就返回false;

2、如果this和obj引用的是不同的对象,返回false;

3、针对类型定义的每个实例字段,都将this对象中的值与obj对象中的值进行比较(通过调用对象的Equals方法)。任何字段不相等,就返回false.

4、返回true,ValueType的Equals方法不掉用Object的Equals方法.

上述3步骤,是通过反射实现,由于CLR的反射机制效率不高,所以在定义自己的值类型的时候,应重写Equals方法来提供自己的实现,从而提高自己类型进行值类型比较时的性能.注:自己的实现不用调用base.Equals().

当我们定义自己的类型时,重写的Equals方法要符合下面几个特性:

1、Equals必须自反 x.Equals(x)肯定返回true.

2、Equlas必须对称 x.Equals(y)和y.Equals(x)必须返回相同的值

3、Equals必须可传递 x.Equals(y)返回true,y.Equals(z)返回true则x.Equals(z)也必须返回true.

4、Equals必须一致,比较的两个值不变,Equals返回值(true或false)也不能变

如果实现的Equals方法不符合上述特性,应用程序就会行为失常.

重写Equals方法必须做以下几件事

1、让类型实现System.IEquatable<T>接口的Equals方法

这个泛型接口允许定义类型安全的Equals方法,通常实现的Equals方法应获取一个Object参数,以便在内部调用类型安全的Equals方法.

2、重载==和!=操作符方法

通常应实现这些操作符方法,在内部调用类型安全的Equals方法.

C# 对象相等性判断和同一性判断的更多相关文章

  1. Js判断对象是否为空,Js判断字符串是否为空

    Js判断对象是否为空,Js判断字符串是否为空,JS检查字符串是否为空字符串 >>>>>>>>>>>>>>>&g ...

  2. 在Map对象中获取属性,注意判断为空

    在Map对象中获取属性,注意判断为空 public static void main(String[] args) { Map map = new HashMap(); Integer i = (In ...

  3. c# 对象相等性和同一性

    一:对象相等性和同一性 System.Object提供了名为Equals的虚方法,作用是在两个对象包含相同值的前提下返回true,内部实现 public class Object { public v ...

  4. js数据类型判断和数组判断

    这么基础的东西实在不应该再记录了,不过嘛,温故知新~就先从数据类型开始吧 js六大数据类型:number.string.object.Boolean.null.undefined string: 由单 ...

  5. 判断逻辑 先判断协议字段返回,再判断业务返回,最后判断交易状态 API密钥

    [微信支付]微信小程序支付开发者文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_1 协议规则 商户接入微信支付, ...

  6. [改善Java代码]用偶判断,不用奇判断

    建议21: 用偶判断,不用奇判断 public class Client { public static void main(String[] args) { Scanner in = new Sca ...

  7. 判断DataTale中判断某个字段中包含某个数据

    // <summary> /// 判断DataTale中判断某个字段中包含某个数据 /// </summary> /// <param name="dt&quo ...

  8. 快学Scala 第十三课 (类型层级,对象相等性)

    Scala 类型层级: 对象相等性: 和Java一样要重写equals方法和hashcode方法 class Student(val id: Int, val name: String) { over ...

  9. java 对象、集合的非空判断

    自我总结,有什么不到位的地方,请各位纠正补充,感激不尽! 目的:使程序更严谨 ***对象验证是否不为空:  if( null != obj ) ***List验证不为空:if( null != lis ...

随机推荐

  1. linux安装mysql~~~mysql5.6.12

    Linux安装mysql服务器 准备: MySQL-client-5.6.12-1.rhel5.i386.rpm MySQL-server-5.6.12-1.rhel5.i386.rpm 首先检查环境 ...

  2. windows开启禁用网卡

    ' 在Windows中实现sudo命令--命令行环境中获取管理员权限 'ShellExecute 方法 '作用: 用于运行一个程序或脚本. '语法 ' .ShellExecute "appl ...

  3. The serializable class XXX does not declare a static final serialVersionUID field of type long

    问题: 在Eclipse中,继承类时,总是提示下面的警告(Warning),按理说警告是没有关系的,但是程序看起来老不爽了,这是强迫症的关系(呵呵) The serializable class XX ...

  4. 简单的cxf-ws 基于web容器

    pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...

  5. 《Forward团队-爬虫豆瓣top250项目-代码设计规范》

    成员:马壮,李志宇,刘子轩,年光宇,邢云淇,张良 1.缩进采用一个Tab键 2.大括号:如: if (条件){ 语句: } 3.分行:不把多条语句放在同一行 4.变量命名:统一用英文 5.注释:注释前 ...

  6. Example11(June 9,2015)

    %--------------sort------------------------------- >> A=[ ; ; ] A = >> B=sort(A,)%A(:,)& ...

  7. [redis]Redis Transaction

    https://github.com/phpredis/phpredis#transactions Transactions multi, exec, discard - Enter and exit ...

  8. EBS获取附件URL

    http://wenku.baidu.com/link?url=MnYX269RBqW9ZRh-4famwduhYq9As0-vsIyVPA7aqv64cdxxjZEOaEE1_KZ9SGjY9qCx ...

  9. MYSQL的数据连接超时时间设置

    大规模多线程操作事务的时候,有时候打开一个链接,会进行等待,这时候如果数据库的超时时间设置的过短,就可能会出现,数据链接自动被释放,当然设置过大也不好,慢SQL或其他因素引起的链接过长,导致整个系统被 ...

  10. C#获取微信二维码显示到wpf

    微信的api开放的二维码是一个链接地址,而我们要将这个二维码显示到客户端.方式很多,今天我们讲其中一种. /// <summary> /// 获取图片路径 /// </summary ...