C#对象的四种比较方式

这篇具有很好参考价值的文章主要介绍了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)与==的区别    

  1. ==操作符判断的是堆栈中的值,Equlas判断的是堆中的值。
  2. C#提供值类型和引用类型:
    • 值类型存储在栈上,故用==判断是直接判断其值是否相等,因为值类型不存在堆中的数据,因此值类型的Equals也是判断数据。即,对于值类型而言,==与Equals相同,均是判断其值是否相等。
    • 对于引用类型而言,其栈中存储的是对象的地址,那么==就是比较两个地址是否相等,即是否指向同一个对象;Equals则是比较两个对象在堆中的数据是否一样,即两个引用类型是否是对同一个对象的引用。

 

   3. String类型特殊:

    • String类型虽然是引用类型,但是对String对象的赋值却按照值类型操作
    • 对str2初始化的时候,并没有重新开辟内存,而是直接将其地址指向str1的内容“hello”。这样一来,string类型虽然是引用类型,但是其==操作和Equals操作都是一样的,均比较值是否相等。

  4. 与GetHashCode()的关系文章来源地址https://www.toymoban.com/news/detail-569341.html

    • 若两对象Equals相等,那么其GetHashCode()必定相等;但是反过来,若GetHashCode()相等,那么这两个对象Equals方法比较结果不一定相同。(为了获取最佳性能,hash函数为对象内容生成的数字是随机分布的,这就意味着,内容不同的对象,有可能生成的数字是一样的,但可以认为这种概率非常小)。

到了这里,关于C#对象的四种比较方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 创建多线程的四种方式

    ① 创建一个类继承 Thread 类,重写 run() 方法 ② 调用 start() 方法启动线程 例: ① 创建类实现 Runnable 接口,重写 run() 方法 ② 以实现类作为构造器参数,创建一个线程( Thread )对象 ③ 调用 start() 方法启动线程 例 注意:实现Runnable接口方式中,调用的不是Thread类的run()方法

    2024年02月10日
    浏览(45)
  • JavaScript中的四种枚举方式

    字符串和数字具有无数个值,而其他类型如布尔值则是有限的集合。 一周的日子(星期一,星期二,...,星期日),一年的季节(冬季,春季,夏季,秋季)和基本方向(北,东,南,西)都是具有有限值集合的例子。 当一个变量有一个来自有限的预定义常量的值时,使用

    2024年02月03日
    浏览(56)
  • STM32的四种开发方式

    首先看下ST官方给出的四种开发方式的比较 寄存器开发 寄存器编程对于从51等等芯片过渡过来的小伙伴并不陌生,不管你是什么库,最终操作的还是寄存器,所以对于标准库、HAL库、LL库都是在寄存器上的编程,所以可以直接在各种库中直接操作寄存器。 但寄存器开发方法到

    2024年02月11日
    浏览(41)
  • CSS中的四种定位方式

    在CSS中定位有以下4种: 静态定位 - static 相对定位 - relative 绝对定位 - absolute 固定定位 - fixed 静态定位是css中的默认定位方式,也就是没有定位。在此定位方式中设置:top,bottom,left,right,z-index 这些属性都是无效的。 相对位置前的位置: 相对位置后的位置: 可以看到该

    2024年02月08日
    浏览(87)
  • Java创建数组的四种方式

    1.使用默认值来初始化 语法: 数组元素类型 [] 数组名称 = new 数组元素类型 [数组长度] EG: int [] nums = new int [5]; //创建了一个类型为int,名字为nums ,长度为5的数组 2.先声明一个数组,再给值 语法: 数据元素类型 [] 数组名称; 数组名称 = new 数组元素类型[数组长度]; EG: int [] nums; num

    2024年02月09日
    浏览(60)
  • 单例模式的四种创建方式

    单例模式是日常开发中最常见的一种设计模式,常用来做为池对象,或者计数器之类的需要保证全局唯一的场景。 单例模式的目的是保证在整个程序中只存在一个对象实例,使用单例一个前提条件就是构造器私有化,不允许通过new 对象的方式。单例模式的实现主要方式有如

    2024年02月01日
    浏览(44)
  • 记录-实现深拷贝的四种方式

    深拷贝:在堆内存中重新开辟一个存储空间,完全克隆一个一模一样的对象 浅拷贝:不在堆内存中重新开辟空间,只复制栈内存中的引用地址。本质上两个对象(数组)依然指向同一块存储空间 使用递归的方式进行对象(数组)的深拷贝 奉上已封装的深拷贝函数👇 上方函

    2023年04月21日
    浏览(39)
  • python导入库的四种方式

    目录 前言 一、import 库名 二、import 库名 as 别名(变量名) 三、from 库名 import 方法名 四、from 库名 import* 库可以抽象的理解为一个工具包,而库里的方法可以理解为工具包里各式各样的工具,每个工具作用不同。 此文例子库名为pygame,也就是工具包的名字,例子方法为ini

    2024年02月05日
    浏览(37)
  • gRpc的四种通信方式详细介绍

    🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础入门篇)》学会Golang语言

    2024年02月11日
    浏览(40)
  • C++文件读取的四种方式

    C++可以根据不同的目的来选取文件的读取方式,目前为止学习了C++中的四种文件读取方式。 C++文件读取的一般步骤: 1、包含头文件 #includefstream 2、创建流对象:ifstream ifs (这里的ifs是自己起的流对象名字) 3、打开文件:file.open(\\\"文件路径\\\",\\\"打开方式\\\"),打开文件后并判断文件是

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包