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方法.
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android 天气APP(十七)热门城市 - 国内城市
- Python 技术篇-PIL库安装及截图功能演示
- Android 天气APP(十八)常用城市
- Android 蓝牙开发(扫描设备、绑定、解绑)
- Python 微信机器人:调用电脑摄像头时时监控功能实现演示,调用电脑摄像头进行拍照并保存。
- Android 天气APP(十九)更换新版API接口(更高、更快、更强)
- Android 天气APP(二十)增加欢迎页及白屏黑屏处理、展示世界国家/地区的城市数据
- Android 天气APP(二十二)改动些许UI、增加更多空气质量数据和生活建议数据展示
- Android 自定义View 之 RectF用法详解
- Android 天气APP(二十五)地图天气(下)嵌套滑动布局渲染天气数据
- Android 天气APP(二十六)增加自动更新(检查版本、通知栏下载、自动安装)
- Android 天气APP(二十七)增加地图天气的逐小时天气、太阳和月亮数据
- Android 天气APP(二十八)地图搜索定位
- DevEco Studio项目构建讲解、编写页面、布局介绍、页面跳转
- Android 天气APP(二十九)壁纸设置、图片查看、图片保存