【转载】C#扫盲之:==/Equals /ReferenceEquals 异同的总结,相等性你真的知道吗?

【转载】C#扫盲之:==/Equals /ReferenceEquals 异同的总结,相等性你真的知道吗?

1.前言

== Equals ReferenceEquals 三个相等性测试,是.NET提供给程序员使用的三个方法,他们之间有什么联系和区别,你真的仔细研究过?虽然之前也多多少少知道一点,但是有时候又难免混淆他们之间的概念和所适用的场合,决定做一个总结系统的描述这三个宝宝

2.值类型比较和引用类型比较

在编程中实际上我们只需要这两种比较,c#中类型也就这两种

  (1)值类型的比较:一般我们就是判断两个值类型实例的各自包含的值是否相等

  (2)引用类型的比较:由于引用类型在内存中的分布有两部分,一个是引用类型的引用(存在于线程栈中),一个是引用类型的值(存在于托管堆);所以我们比较引用类型也就存在两种比较

默认情况下:值类型比较的是两个值是否相等(不装箱情况下),引用类型比较的是两个引用是否相等。

3.==, Equals,ReferenceEquals 的阐述
3.1==

定义:静态相等符号,对应存在的!=,这个符号是一个可以重载的二元操作符,可以用于比较两个对象是否相等。使用==比较对象时,C#在编译时就决定了所比较的类型,而且不会执行任何虚方法(Object.Equals)。这是大家所期望的相等行比较。

  • 对于内置值类型,==判断的是两个对象的代数值是否相等。它会根据需要自动进行必要的类型转换,并根据两个对象的值是否相等返回true或者false
  • 对于引用类型,则==一般情况下比较的这是引用类型的引用是否相等。

注意:但是某些内置的引用类型重载了==符号,例如string就重载==,使其比较的不是两个字符串的引用,而是比较的两个字符串字面量是否相等,如下图,所以对于引用类型最好不要使用==符号进行相等性比较,避免混淆。【对于引用类型利用==除了string是比较其值外,其余都是比较其引用,因为string是经常需要操作,所以会直接比较其值,所以会对其特殊对待,所以如果遇见特殊的引用类型需要查看一下是否进行了==重载,默认情况大家都可以把==在比较引用类型时当成比较引用!

<span>【转载】C#扫盲之:==/Equals /ReferenceEquals 异同的总结,相等性你真的知道吗?</span>

  值类型的==比较:虽然i和j在栈上具有不同的内存空间,但是他们的代数值都为5;m和n类型被自动转换并比较代数值

 int i = 5;
 int j = 5;
 Console.WriteLine(i == j);//值类型比较代数值 输出True

 int m = 6;
 double n = 6.0;
 Console.WriteLine(m == n);//类型自动转换并比较数值 输出True

  引用类型==比较:如下代码,两个object对象都在堆上申请了空间,在线程栈上存在两个不同的引用,所以输出结果为False

object obj1 = new object();
object obj2 = new object();
Console.WriteLine(obj2==obj1);//引用类型比较引用 输出False

 3.2 Equals

  定义:Equals属于Object的实例方法,用于比较两个对象的引用是否相等,注意:对于Object对象比较的是引用!

     然而对于值类型,类型相同(不会进行类型自动转换),并且数值相同(对于struct的每个成员都必须相同),则Equals返回 true,否则返回false。这是为什么呢?                 这是因为内置的值类型都重写了Object.Equals方法,所以值类型的Equals方法与引用类型的Equals就产生了不同的效果。

      Equals在程序运行时决定比较的类型–根据对象的实际类型进行比较,根据对象的类型调用他们各自的Equals虚方法。

            int i = 5;
            int j = 5;
            Console.WriteLine(i.Equals(j));//值类型比较 输出True

            int m = 6;
            double n = 6.0;
            Console.WriteLine(m.Equals(n));//类型不会自动转换并比较数值 输出False

            object obj1 = new object();
            object obj2 = new object();
            Console.WriteLine(obj2.Equals(obj1));//引用类型比较 输出False
            Console.WriteLine(obj2.Equals(string.Empty));//输出False,比较量对象的类型不同直接返回False      

3.3 ReferenceEquals

  定义:Object的静态方法,比较两对象的引用是否相等,值类型和引用类型都是一样。

            int i = 5;
            int j = 5;
            Console.WriteLine(object.ReferenceEquals(i, j));//输出False

            int m = 6;
            double n = 6.0;
            Console.WriteLine(object.ReferenceEquals(m, n));//输出False

            object obj1 = new object();
            object obj2 = new object();
            Console.WriteLine(object.ReferenceEquals(obj1, obj2));//输出False

4.三种比较方法的相同和区别

通过以上的探讨我们知道

ReferenceEquals比较对象的引用是否相同,而且是安全的比较
==和Equals异同

相同点: 对于值类型 都是比较代数值是否相等
不同点:(1)对于值类型比较,==会进行类型的自动转换,然后比较代数值,Equals则不会进行转换,先比较类型,再比较值,如果类型不同直接返回false
   (2)==比较是安全的比较,也就是说两对象为任何值都可以进行比较,不会抛出异常;而Equals的比较则是不安全的,由于在Equals在运行时才会进行真正的比较,有可能调用Equals的调用者是NULL,编译通过,但是运行时则会抛出异常

<span>【转载】C#扫盲之:==/Equals /ReferenceEquals 异同的总结,相等性你真的知道吗?</span>

所以对于引用类型是要使用实例的Equals进行比较时,一定不要忘记检查调用者对象是否为空。而Object提供的静态Equals方法也是安全的不需要检查,下面的方法等效于Object提供的静态Equals方法

public static bool AreEqual(object obj1, object obj2)
 {
    if (obj1 == null)
        return obj2 == null;
    return obj1.Equals(obj2);
 }

由于本人才学识浅,描述难免纰漏,如有错误,欢迎指出。么么!

参考资料:
http://www.cnblogs.com/yang_sy/p/3582946.html
http://www.cnblogs.com/zagelover/articles/2741409.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119341.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • hanoi 塔问题_Hanoi塔

    hanoi 塔问题_Hanoi塔importjava.util.Scanner;/* *汉罗塔问题 */publicclassHanoiExec{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubSystem.out.println(“请输入盘子数n”);Scanner

    2022年10月12日
    2
  • leetcode 792_leetcode5421编码

    leetcode 792_leetcode5421编码给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。示例 1:输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”输出:true示例 2:输

    2022年8月9日
    5
  • MySQL数据库使用命令行备份|MySQL数据库备份命令

    MySQL数据库使用命令行备份|MySQL数据库备份命令转至  神马和浮云 ,命令未测试,主要是方便操作mysql时需要而记的笔记  例如:数据库地址:127.0.0.1数据库用户名:root数据库密码:pass数据库名称:myweb 备份数据库到D盘跟目录mysqldump-h127.0.0.1-uroot-ppassmyweb&gt;d:/backupfile.sql备份到当前目录备份MySQ…

    2022年6月10日
    34
  • zip文件加密的几种破解方法

    zip文件加密的几种破解方法一、使用ZipCenOp.jar(需要java环境),在cmd中使用java-jarZipCenOp.jarrxxx.zip成功后压缩包可以直接打开ZipCenOp.jar链接:https://pan.baidu.com/s/1e0Ni2OjxmYEdOY7gGbv6gg提取码:29qi二、使用winRAR进入工具,压缩修复文件,修复完后压缩包就可以打开了上述两种…

    2022年6月1日
    293
  • UML图详解(八)状态机(状态图和活动图)

    UML图详解(八)状态机(状态图和活动图)一、概念状态图和活动图是状态机的两种表现形式。利用状态机可以精确地描述对象的行为。从对象的初始状态起,开始响应事件并执行某些动作,这些事件引起状态的转换;对象在新状态下又开始响应事件和执行动作,如此连续进行直到终结状态。二、状态图状态图(StateDiagram)=状态(State)+迁移(Transition)一个状态图描述一个状态机。 状态图表现从一个状态到另一个…

    2022年6月2日
    49
  • vue 正则表达式验证_vue表单自定义验证

    vue 正则表达式验证_vue表单自定义验证首先需要自己写正则表达式,正则学得不好就不乱指点了=>方法1如果你是单独建的js文件先引入正则表达式文件才进行下一步或者直接在组件内写正则2data({constregExpID=(rule,value,callback)=>{//regExpID自定义类名if(value===”){//value验证的值不要更改会自动匹配你所需要验证的值ca…

    2025年8月22日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号