C# 中有两种不同的相等:引用相等和值相等。值相等是大家普遍理解的意义上的相等:它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。引用相等意味着要比较的不是两个对象,而是两个对象引用,这两个对象引用引用的是同一个对象。这可以通过简单的赋值来实现,如下面

System.Object a = new System.Object();
System.Object b = a;
System.Object.ReferenceEquals(a, b); //returns true

在上面的代码中,只存在一个对象,但存在对该对象的多个引用:a 和 b。由于它们引用的是同一个对象,因此具有引用相等性。如果两个对象具有引用相等性,则它们也具有值相等性,但是值相等性不能保证引用相等性。

若要检查引用相等性,应使用 ReferenceEquals

1、比较引用类型相等性

System.Object定义了3个不同方法,来比较对象的相等性:ReferenceEquals()和两个版本的Equals()。再加上比较运算符(==)

ReferenceEquals(),静态方法,不能被重写,测试两个引用是否引用类的同一个实例,特别是两个引用是否包含相同的地址。
如果提供的两个引用引用同一个对象实例,则ReferenceEquals()总是返回true,否则返回false,但是他认为null等于null:

System.Object a = new System.Object();
System.Object b = a;
System.Object c=new System.Object();
System.Object.ReferenceEquals(a, b); //returns true
bool flag=ReferenceEquals(null,null) //return true
bool flag1=ReferenceEquals(a,c) //return false
bool flag2=ReferenceEquals(null,a) //return false

另外,ReferenceEquals()在应用于值类型是,他总是返回false,因为为了调用这个方法,值类型需要装箱到对象中,
即使使用下面的代码:

bool flag=ReferenceEquals(v,v);  //v是值类型

也会返回false,应为在转换每个参数时,v都会被单独装箱,这意味着会得到不同的引用,也就是说ReferenceEquals() 来比较值类型
实际上没什么意义。

2、静态的Object.Equals(Object objA,Object objB)方法

如果如果objA 是与 objB 相同的实例,或者如果两者均为空引用,或者如果 objA.Equals(objB) 返回 true,则为 true;否则为 false。

Equals 的默认实现仅支持引用相等,但派生类可重写此方法以支持值相等。
对于引用类型,相等定义为对象相等;即这些引用是否引用同一对象。对于值类型,相等定义为按位相等。ValueType 类支持值类型。
在调用 objA.Equals(objB) 前,此方法首先检查两个参数是否均为空引用。

String s1="Hello";
String s2="World";
String s3="Hello"; Object.Equals(s1,s2) //return false
Object.Equals(s1,s3) //return true s2=null;
Object.Equals(s1,s2) //return false s1=null;
s2=null;
Object.Equals(s1,s2) //return true

3、虚拟的 Object.Equals(obj)方法

如果指定的 Object 等于当前的 Object,则为 true;否则为 false。

此方法可由派生类重写。例如,如果两个对象表示相同的值,则许多基数据类型返回 true;否则返回 false。 此方法仅比较基元和对象。若要比较更复杂的结构(如对象数组),必须重写该方法。 下面的语句对于 Equals 方法的所有实现均必须为真。

Equals 的实现必须不引发异常。 对于某些类型的对象,最好让 Equals 测试值相等性而非引用相等性。如果两个对象具有相同的“值”,那么即使它们不是同一实例,这样的 Equals 实现仍返回 true。类型实施者决定对象的“值”的构成,但这通常是存储在对象的实例变量中的部分或全部数据。例如,String 的值基于字符串的字符;对于两个按同样的顺序包含完全相同的字符的字符串实例,String 类的 Equals 方法返回 true

int i=;
int j=;
bool flag=i.Equals(j); //只类型比较,返回true
double k=9.0;
bool flag1=i.Equals(k);// 类型不会自动转换并比较数值,返回false Object objA=new Object();
Object objB=new Object(); bool flag2=objA.Equals(objB); //引用比较,返回false
bool flag3=objA.Equals(String.Empty); //比较对象的类型不同,直接返回false

另外,Microsoft已经在System.ValueType类中重载了实例方法Equals(),以便对值类型进行合适的相等性测试。
如果调用sA.Equals(sB),其中sA和sB是某个结构的实例,则根据sA和sB是否在其所有的字段包含相同的值,而返回true或false

4、==比较运算符

对于值类型 都是比较代数值是否相等。

最好将比较运算符看作严格的值比较和严格的引用比较之间的中间项,在大多数情况下,下面代码表示正在比较引用:
bool b=(x==y) //x和y都是引用类型
在某些情况下,最好重写比较运算符(==),以执行值的比较,例如:System.String类,Microsoft重写了==运算符,用来比较
字符串的内容,而不是比较他们的引用

5、==和Equals异同

相同点: 对于值类型 都是比较代数值是否相等
不同点:(1)对于值类型比较,==会进行类型的自动转换,然后比较代数值,Equals则不会进行转换,先比较类型,再比较值,如果类型不同直接返回false

细说C#的ReferenceEquals,Equals和==比较运算符的更多相关文章

  1. Java提高篇——equals()方法和“==”运算符

    equals() 超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等.该方法的源码如下: public boolean equals(Object obj) { retu ...

  2. java中的equals方法与"=="运算符解说

    在编程的时候,我们可能经常会用到equals方法,那么这个equals方法和运算符“==”有什么样的区别? public class equal { /** * @param args */ publ ...

  3. C#中==运算符

    在这篇博客中,我们将介绍如下内容: ==运算符与基元类型 ==运算符与引用类型 ==运算符与String类型 ==运算符与值类型 ==运算符与泛型 ==运算符与基元类型 我们分别用两种方式比较两个整数 ...

  4. C#中 Reference Equals, == , Equals的区别

    原文地址:http://blog.csdn.net/wuchen_net/archive/2010/03/23/5409327.aspx ReferenceEquals, == , Equals Eq ...

  5. C#高级编程9-第7章 运算符和类型强制转换

    运算符和类型强制转换 1.运算符 运算符的简化操作 条件运算符: if-else的简化操作,也称三元运算符.如果条件为真,返回一个值,为假返回另外一个值. condition?true_value:f ...

  6. String类中的equals()方法

    在Java中,每一个对象都有一个地址空间,在这空间保存着这个对象的值. equals 比较的是值,==比较的地址以及值. 01: public class StringExample02: {03: ...

  7. 快看Sample代码,速学Swift语言(3)-运算符

    运算符是用来检查,更改或组合值的特殊符号或短语.Swift提供的很多常规的运算符,如+.-.*./.%.=.==等,以及逻辑运算的&&.||等等,基本上不需要重复介绍,我们在这里只需要 ...

  8. [知识库分享系列] 二、.NET(ASP.NET)

    最近时间又有了新的想法,当我用新的眼光在整理一些很老的知识库时,发现很多东西都已经过时,或者是很基础很零碎的知识点.如果分享出去大家不看倒好,更担心的是会误人子弟,但为了保证此系列的完整,还是选择分享 ...

  9. 多个提高C#编程能力的建议

    1.总是用属性 (Property) 来代替可访问的数据成员 2.在 readonly 和 const 之间,优先使用 readonly 3.在 as 和 强制类型转换之间,优先使用 as 操作符 4 ...

随机推荐

  1. js 页面 保持状态 的方法

    A -> B 带参数进去B页面, 刷新B页面还  保持状态 单机下一页, 改变请求参数, A->B 不带参数进去B页面 (不存在)当前状态保存在cookies中, 刷新页面,判断cooki ...

  2. zookeeper3.5.5集群部署

    ZooKeeper是一个为分布式应用所设计的分布的.开源的协调服务,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,简化分布式应用协调及其管理的难度,提供高性能的分布式服务.ZooKeeper ...

  3. Mybatis学习笔记之---多表查询(2)

    Mybatis多表查询(2) (一)举例 用户和角色 一个用户可以有多个角色,一个角色可以赋予多个用户 (二)步骤 1.建立两张表:用户表,角色表,让用户表和角色表具有多对多的关系.需要使用中间表,中 ...

  4. Shell 变量/echo命令

    Shell 教程 Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面,用户 ...

  5. Oracle JET Model 数据获取与使用

    Oracle JET 应用程序数据可以来自生成 JSON 数据的任何 Web 数据源,例如 REST 服务,服务器发送事件(SSE)或 WebSocket .此外,Oracle JET 还提供了基于 ...

  6. Python的复制,浅拷贝和深拷贝

    https://www.cnblogs.com/xueli/p/4952063.html 如果给一个变量赋值一个对象,那么新变量和原对象变量将会是同一个引用,其中一方改变,另一方也会改变. 该问题可以 ...

  7. hadoop stop-dfs.sh 无法停止 namenode datanode

    原因: HADOOP_PID_DIR 默认为 /tmp 目录,如果长期不访问/tmp/目录下的文件,文件会被自动清理,因此 stop-dfs.sh 无法根据 pid 停止 namenode, data ...

  8. E: 错误,pkgProblemResolver::Resolve 发生故障,这可能是有软件包被要求保持现状的缘故。 E: 无法更正依赖关系

    mentohust:i386 已经是最新的版本了. 您可能需要运行"apt-get -f install"来纠正下列错误: 下列软件包有未满足的依赖关系:  mentohust:i ...

  9. 在JavaScript中引用类型和值类型的区别

    一.存储方式不一样 基本数据类型 变量存储的是简单的数据段,存储的是具体的值,是轻量级的数据存储方式 引用类型 引用类型的值,可以由多个值构成的对象,引用类型的变量存储的是对象引用地址.引用类型是重量 ...

  10. c# 窗口关闭方法

    背景:点击datagridview某条信息弹出信息详情窗口,当连续点击时需要关闭之前的详情窗口. 实现方式: 父窗口中 全局创建子窗口(MsgDetailFrm  ): MsgDetailFrm de ...