-
C#对象的四种比较方式
1.ReferenceEquals(object o1, object o2):
- 静态方法:比较两个对象的引用,引用相同返回true,否则返回false,同为null是返回true;ReferenceEquals进行值类型比较时总是返回false,因为两个值类型需要分别装箱到对象中,是不同的引用 ;
- 从名称中便可知它用来比较两者是否是相同的引用,我们也永远不应该去重写该方法。
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; //ReferenceEquals比较两个对象的引用,同为null是返回true Console.WriteLine("ReferenceEquals(zs, ls) : " + ReferenceEquals(zs, ls)); // False Console.WriteLine("ReferenceEquals(zs, zsCopy) : " + ReferenceEquals(zs, zsCopy)); //True Console.WriteLine("ReferenceEquals(ls, zsCopy) : " + ReferenceEquals(ls, zsCopy)); //Fasle Console.WriteLine("ReferenceEquals(null, null) : " + ReferenceEquals(null, null)); //True Console.WriteLine("ReferenceEquals(zs, null) : " + ReferenceEquals(zs, null)); //False Console.WriteLine("ReferenceEquals(1, 1) : " + ReferenceEquals(1, 1)); //False
2.Equals(object o):
- 虚方法:比较两个对象的引用,由于是虚方法所以可以在自己的类中重写它,按值来比较对象
- 重写Equals应该遵循的原则:自反性、对称性、传递性。即:a=a;若a=b,则b=a;若a=b,b=c,则a=c;另外两个对象要么相等要不不等,所以该方法不应该抛出异常;
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; //虚拟Equals方法,比较引用,可以重写比较值 Console.WriteLine("zs.Equals(ls) : " + zs.Equals(ls)); //Fasle Console.WriteLine("zs.Equals(zsCopy) : " + zs.Equals(zsCopy)); //True Console.WriteLine("ls.Equals(zsCopy) : " + ls.Equals(zsCopy)); //False Console.WriteLine("zs.Equals(null) : " + zs.Equals(null)); //False Console.WriteLine("1.Equals(1) : " + 1.Equals(1)); //True
3.Equals(object o1, object o2):
- 静态方法:比较两个对象的引用,先判断两个对象是否为空,如果都不为空,则调用虚拟Equals方法;
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; //静态Equals方法先比较两个对象是否为空,如果都不为空,则调用虚拟Equals方法 Console.WriteLine("Person.Equals(zs, ls) : " + Person.Equals(zs, ls)); //False Console.WriteLine("Person.Equals(zs, zsCopy) : " + Person.Equals(zs, zsCopy)); //True Console.WriteLine("Person.Equals(ls, zsCopy) : " + Person.Equals(ls, zsCopy)); //False Console.WriteLine("Person.Equals(null, null) : " + Person.Equals(null, null)); //True Console.WriteLine("Person.Equals(zs, null) : " + Person.Equals(zs, null)); //Fasle Console.WriteLine("Person.Equals(1, 1) : " + Person.Equals(1, 1)); //True
4.object1 == object2:
- 比较运算符:可以重写;对于引用类型,默认是比较引用的(System.String除外)来源,对于值类型默认比较值;
-
对于自定义的结构,如果不显示重载operator方法,则无法使用。
由于在C#中要求比较运算符必须成对重载,重载==运算符的同时也必须重载!=运算符,否则也会产生编译错误。
如果要重载的话,运算符"=="、"!=" 与 Equals方法、GetHashCode方法应该同时被重载,因为他们应该保持同样的相等逻辑。但不要再==中调用Equals,最好是在Equals中调用==。
Person zs = new Person("ZhangSan",28); Person ls = new Person("LiSi",20); Person zsCopy = zs; String str1 = "Hello"; String str2 = "Hello"; String str3 = str1; //比较运算符比较引用,可以重写 Console.WriteLine("zs == ls : " + (zs == ls)); //False Console.WriteLine("zs == zsCopy : " + (zs == zsCopy)); //True Console.WriteLine("ls == zsCopy : " + (ls == zsCopy)); //False Console.WriteLine("zs == null : " + (zs == null)); //False Console.WriteLine("1 == 1 : " + (1 == 1)); //True Console.WriteLine("str1 == str2 :" + (str1 == str2));//True Console.WriteLine("str1 == str3 :" + (str1 == str3));//True Console.WriteLine("str2 == str3 :" + (str2 == str3));//True
Equals(object o)与==的区别
- ==操作符判断的是堆栈中的值,Equlas判断的是堆中的值。
- C#提供值类型和引用类型:
-
- 值类型存储在栈上,故用==判断是直接判断其值是否相等,因为值类型不存在堆中的数据,因此值类型的Equals也是判断数据。即,对于值类型而言,==与Equals相同,均是判断其值是否相等。
- 对于引用类型而言,其栈中存储的是对象的地址,那么==就是比较两个地址是否相等,即是否指向同一个对象;Equals则是比较两个对象在堆中的数据是否一样,即两个引用类型是否是对同一个对象的引用。
3. String类型特殊:
-
- String类型虽然是引用类型,但是对String对象的赋值却按照值类型操作
- 对str2初始化的时候,并没有重新开辟内存,而是直接将其地址指向str1的内容“hello”。这样一来,string类型虽然是引用类型,但是其==操作和Equals操作都是一样的,均比较值是否相等。
4. 与GetHashCode()的关系
-
- 若两对象Equals相等,那么其GetHashCode()必定相等;但是反过来,若GetHashCode()相等,那么这两个对象Equals方法比较结果不一定相同。(为了获取最佳性能,hash函数为对象内容生成的数字是随机分布的,这就意味着,内容不同的对象,有可能生成的数字是一样的,但可以认为这种概率非常小)。
出处:https://www.cnblogs.com/LXLR/p/17558349.html
栏目列表
最新更新
python爬虫及其可视化
使用python爬取豆瓣电影短评评论内容
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
uniapp/H5 获取手机桌面壁纸 (静态壁纸)
[前端] DNS解析与优化
为什么在js中需要添加addEventListener()?
JS模块化系统
js通过Object.defineProperty() 定义和控制对象
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比