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

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. C和指针小结(C/C++程序设计)

    C和指针 相关基础知识:内存的分配(谭浩强版) 1.整型变量的地址与浮点型/字符型变量的地址区别?(整型变量/浮点型变量的区别是什么) 2.int *p,指向整型数据的指针变量. 3.通过指针变量访问 ...

  2. 如何设置vim中tab键缩进---配置初始化设置

    转载自:http://blog.51cto.com/xuding/1725376:加了一些补充说明 问题: Linux系统下,Tab键默认为8个字符,需呀将其修改为4个字符的方式使用 步骤: 1.在用 ...

  3. 在 Java 中使用 protobuf

    在 Java 中使用 protobuf 从 https://github.com/google/protobuf/releases 下载编译器,并设置环境变量. 创建java项目添加protobuf- ...

  4. underscore functions

    // 创建一个用于设置prototype的公共函数对象 var ctor = function() {}; 1..bind(function, object, [*arguments]) :绑定fun ...

  5. [php] try - catch exceptiong handler

    //http://stackoverflow.com/questions/1241728/can-i-try-catch-a-warningOne possibility is to set your ...

  6. Create Your Content and Structure

    The original page source Content is the most important aspect of any site. So let's design for the c ...

  7. 导出delphi编写的ios程序在xcode下的日志

  8. Android ADB命令基本常用操作

    电脑配置好环境变量之后呢,在cmd里面自测一下,是否配置OK: 1.查看目前连接的设备: adb devices 2.使目前连接的设备重启: adb reboot 3.有时候由于设备冲突导致adb出现 ...

  9. Android adb shell data目录,Permission denied

    Android adb shell进入data目录,Permission denied 权限被拒绝 在shell里面输入su root,去申请root权限,注意:有小部分手机是需要点击授权,再次执行c ...

  10. JavaLogin小框架制作【精品博客】

    做一个小登录接口方法,让用户传入用户名,密码,就可以知道登录的结果信息,并以接口监听的方式控制. 先看客户端执行效果: 输入正确: 输入错误: 模拟客户端使用登录小框架: package com.de ...