细说C#的ReferenceEquals,Equals和==比较运算符
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和==比较运算符的更多相关文章
- Java提高篇——equals()方法和“==”运算符
equals() 超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等.该方法的源码如下: public boolean equals(Object obj) { retu ...
- java中的equals方法与"=="运算符解说
在编程的时候,我们可能经常会用到equals方法,那么这个equals方法和运算符“==”有什么样的区别? public class equal { /** * @param args */ publ ...
- C#中==运算符
在这篇博客中,我们将介绍如下内容: ==运算符与基元类型 ==运算符与引用类型 ==运算符与String类型 ==运算符与值类型 ==运算符与泛型 ==运算符与基元类型 我们分别用两种方式比较两个整数 ...
- C#中 Reference Equals, == , Equals的区别
原文地址:http://blog.csdn.net/wuchen_net/archive/2010/03/23/5409327.aspx ReferenceEquals, == , Equals Eq ...
- C#高级编程9-第7章 运算符和类型强制转换
运算符和类型强制转换 1.运算符 运算符的简化操作 条件运算符: if-else的简化操作,也称三元运算符.如果条件为真,返回一个值,为假返回另外一个值. condition?true_value:f ...
- String类中的equals()方法
在Java中,每一个对象都有一个地址空间,在这空间保存着这个对象的值. equals 比较的是值,==比较的地址以及值. 01: public class StringExample02: {03: ...
- 快看Sample代码,速学Swift语言(3)-运算符
运算符是用来检查,更改或组合值的特殊符号或短语.Swift提供的很多常规的运算符,如+.-.*./.%.=.==等,以及逻辑运算的&&.||等等,基本上不需要重复介绍,我们在这里只需要 ...
- [知识库分享系列] 二、.NET(ASP.NET)
最近时间又有了新的想法,当我用新的眼光在整理一些很老的知识库时,发现很多东西都已经过时,或者是很基础很零碎的知识点.如果分享出去大家不看倒好,更担心的是会误人子弟,但为了保证此系列的完整,还是选择分享 ...
- 多个提高C#编程能力的建议
1.总是用属性 (Property) 来代替可访问的数据成员 2.在 readonly 和 const 之间,优先使用 readonly 3.在 as 和 强制类型转换之间,优先使用 as 操作符 4 ...
随机推荐
- mysql AUTO INCREMENT字段 语法
mysql AUTO INCREMENT字段 语法 作用:在新记录插入表中时生成一个唯一的数字 说明:我们通常希望在每次插入新记录时,自动地创建主键字段的值.我们可以在表中创建一个 auto-incr ...
- 原生JS获取li中的内容
- Maven手动命令行导入ojdbc6
Maven项目中导入Oracle的驱动包时,可能会出现像我一样下载资源不成功的情况,如下图所示: 出现这种情况的原因其实是因为Oracle的授权问题,这样的话,我们在需要使用Oracle的驱动包时, ...
- #381 Div2 Problem C Alyona and mex (思维 && 构造)
题意 : 题目的要求是构造出一个长度为 n 的数列, 构造条件是在接下来给出的 m 个子区间中, 要求每一个子区间的mex值最大, 然后在这 m 个子区间产生的mex值中取最小的输出, 并且输出构造出 ...
- Anaconda安装PyTorch
Anaconda是一个Python语言管理器,支持安装基于Python的开发包,例如tensorflow.Pytorch等,以及各种基于Python的IDE. https://www.jb51.net ...
- 【转】Django之Model层的F对象,Q对象以及聚合函数
转自:https://blog.csdn.net/wsy_666/article/details/86692050 一.F对象: 作用:用于处理类属性(即model的某个列数据),类属性之间的比较.使 ...
- HDU 2147--HDU 2147(博弈)--我可能做了假题。。。
kiki's game Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 40000/1000 K (Java/Others) Total Su ...
- python学习之路(22)
使用模块 Python本身就内置了很多非常有用的模块,只要安装完毕,这些模块就可以立刻使用. 我们以内建的sys模块为例,编写一个hello的模块: #!/usr/bin/env python # - ...
- Spring各种类型数据的注入
直接上代码: 一个MessageBean类 package com.henu.spring; import java.util.*; public class MessageBean { privat ...
- leetcode 590.N-ary Tree Postorder Traversal N叉树的后序遍历
递归方法 C++代码: /* // Definition for a Node. class Node { public: int val; vector<Node*> children; ...