C# 对象相等性判断和同一性判断
在日常开发中经常需要编写代码比较不同的对象。例如,有时需要将对象都放到一个集合中,并编写代码对集合中的对象进行排序、搜索或者比较。
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# 对象相等性判断和同一性判断的更多相关文章
- Js判断对象是否为空,Js判断字符串是否为空
Js判断对象是否为空,Js判断字符串是否为空,JS检查字符串是否为空字符串 >>>>>>>>>>>>>>>&g ...
- 在Map对象中获取属性,注意判断为空
在Map对象中获取属性,注意判断为空 public static void main(String[] args) { Map map = new HashMap(); Integer i = (In ...
- c# 对象相等性和同一性
一:对象相等性和同一性 System.Object提供了名为Equals的虚方法,作用是在两个对象包含相同值的前提下返回true,内部实现 public class Object { public v ...
- js数据类型判断和数组判断
这么基础的东西实在不应该再记录了,不过嘛,温故知新~就先从数据类型开始吧 js六大数据类型:number.string.object.Boolean.null.undefined string: 由单 ...
- 判断逻辑 先判断协议字段返回,再判断业务返回,最后判断交易状态 API密钥
[微信支付]微信小程序支付开发者文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_1 协议规则 商户接入微信支付, ...
- [改善Java代码]用偶判断,不用奇判断
建议21: 用偶判断,不用奇判断 public class Client { public static void main(String[] args) { Scanner in = new Sca ...
- 判断DataTale中判断某个字段中包含某个数据
// <summary> /// 判断DataTale中判断某个字段中包含某个数据 /// </summary> /// <param name="dt&quo ...
- 快学Scala 第十三课 (类型层级,对象相等性)
Scala 类型层级: 对象相等性: 和Java一样要重写equals方法和hashcode方法 class Student(val id: Int, val name: String) { over ...
- java 对象、集合的非空判断
自我总结,有什么不到位的地方,请各位纠正补充,感激不尽! 目的:使程序更严谨 ***对象验证是否不为空: if( null != obj ) ***List验证不为空:if( null != lis ...
随机推荐
- pyhthon lambda
lambda x:x+1(1) >>>2 可以这样认为,lambda作为一个表达式,定义了一个匿名函数,上例的代码x为入口参数和出口参数,x+1为函数体,(1)为x的入口初始值, 用 ...
- 编写属于自己的linux命令
开篇: 问题和解决思路 在使用一些基础IDE时,工具经常会在我们建立特定文件时给我们一个已经有了一些特定代码的模板文件,但是在linux开发时,没有这样的IDE,怎么办?虽然代码量不是很多,但是能一次 ...
- (快速幂)Key Set--hdu--5363
链接: http://acm.hdu.edu.cn/showproblem.php?pid=5363 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- java 泛型的类型擦除和桥方法
oracle原文地址:https://docs.oracle.com/javase/tutorial/java/generics/erasure.html 在Java中,泛型的引入是为了在编译时提供强 ...
- SoC开发板设置网口IP为固定IP
vi /etc/network/interfaces 编辑这个文件 #iface eth0 inet dhcp 找到修改这个,前面加# iface eth0 inet static 改为静态分配i ...
- hdu 4993
http://acm.hdu.edu.cn/showproblem.php?pid=4993 满足ax + by = c的x,y对数 水题,暴力 #include <cstdio> #in ...
- 结对编程--四则运算(Java)梅进鹏 欧思良
结对编程--四则运算(Java)梅进鹏 欧思良 Github项目地址:https://github.com/MeiJinpen/Arithmetic 功能要求 题目:实现一个自动生成小学四则运算题目的 ...
- js常用的原生方法
JavaScript pow() 方法 pow() 方法可返回 x 的 y 次幂的值 语法 Math.pow(x,y) 参数 描述 x 必需.底数.必须是数字. y 必需.幂数.必须是数字. 返回值 ...
- SYS远程连接出错ORA-01031:Insufficient privileges
http://blog.sina.com.cn/s/blog_5f266ec50100m052.html SYS远程连接出错ORA-01031:Insufficient privileges. 现象: ...
- 在TFS持续集成(持续发布)中执行Telnet任务
Telnet是一种在因特网或局域网上使用虚拟终端连接,提供双向交互式文本通信设备的协议. 它是最早的互联网通讯协议之一.自1969年启用以来,已经经过了将近50年时间,在开放式的操作系统中拥有广泛的用 ...