C#中Equals 与== 的区别
这个问题听说是大公司面试都会问的问题,以前不怎么了解,好奇心勾引我来研究一下
首先从值类型分析,先写几句简单的代码供测试用,二行语句输出的都是true,
说明==与Equals功能是相同的, 判断的都是数值.

进入int内部查看下
重写Equals(object obj)

重载Equals(int obj)

可以看得出int.Equals是以自身与目标值进行比较,跟==是相同的功能.
为了确定下其它值类型Equlas与==是否也是一样,再选一个float类型进行查看


其次开始分析下所有类型的基类Object,也写几句简单代码进行测试,二行语句输出的都是false
说明==与Equals功能是相同的, 判断的都是引用地址

也是进入object内部查看下

继续进入RuntimeHelpers中查找Equals

发现这里没有代码了,点击左边的按钮返回到object.Equals

接着分析下引用类型中的String,也写几句简单代码进行测试,二行语句输出的都是true

这就有意思了,为啥输出结果都是true呢
按常规理解来说
使用new关键字在托管堆中申请内存存储string类型数据,然后返回内存地址赋值给
变量,使之指向托管堆中的string类型的对象
每次实例化的对象在托管堆中的地址都不相同才对。
带着疑问还是进入String内部进行一探究尽

可以看到内部对运算符==进行了重载,== 和 Equals也是相同的功能
继续查看Equals

进入EqualsHelper,好长的一大段
private unsafe static bool EqualsHelper(String strA, String strB)
{
Contract.Requires(strA != null);
Contract.Requires(strB != null);
Contract.Requires(strA.Length == strB.Length);
//保存当前String长度
int length = strA.Length;
//固定住二个字符串的首字符地址
fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
{
//定义二个指针用来保存字符串首地址
char* a = ap;
char* b = bp;
//下面判断是否是AMD64位系统,我这不是就往下执行
// unroll the loop
#if AMD64
// for AMD64 bit platform we unroll by 12 and
// check 3 qword at a time. This is less code
// than the 32 bit case and is shorter
// pathlength while (length >= )
{
if (*(long*)a != *(long*)b) return false;
if (*(long*)(a+) != *(long*)(b+)) return false;
if (*(long*)(a+) != *(long*)(b+)) return false;
a += ; b += ; length -= ;
} #else
//A段感觉是多余的,直接执行B段就完事
//判断字符串A长度是否大于10,为真的话每次读取四个字节进行比较
//如果不相同就直接返回false,最后指针向后移动10个字节,长度减少10
while (length >= )
{
if (*(int*)a != *(int*)b) return false;
if (*(int*)(a+) != *(int*)(b+)) return false;
if (*(int*)(a+) != *(int*)(b+)) return false;
if (*(int*)(a+) != *(int*)(b+)) return false;
if (*(int*)(a+) != *(int*)(b+)) return false;
a += ; b += ; length -= ;
}
#endif // This depends on the fact that the String objects are
// always zero terminated and that the terminating zero is not included
// in the length. For odd string sizes, the last compare will include
// the zero terminator. //B段
//这里是前10个字节的匹配情况下,从+10开位置开始继续每四个字节的进行比较
//只要不匹配,跳出循环,那长度肯定肯定不为0, 这里break也是多余,直接return false
//如果所有字节都匹配,最终长度为0,跳出循环,返回真
while (length > )
{
if (*(int*)a != *(int*)b) break;
a += ; b += ; length -= ;
} return (length <= );
}
}
经过漫长的分析可以得出结论,== 与Equals比较的是每个字符,而并不是比较的引用地址
试试自定义的引用类型,创建一个类.先写几句简单的代码供测试用,二行语句输出的都是false

说明自定义的引用类型 == 与Equals也是相同,比较的都是引用地址
结论就是不管是==还是Equals其结果都是相同的
当类型是值类型时,比较是数值
当类型是引用类型时,比较的是引用地址,除了String类型比较的是引用地址下的内容
C#中Equals 与== 的区别的更多相关文章
- java中equals和==的区别 (转)
java中equals和==的区别 值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...
- 【转】Java中equals和==的区别
[转]Java中equals和==的区别 java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boole ...
- C#中 Equals和= =的区别
C#中 Equals和= =的区别 前言:最近感觉技术进步实在是太慢,一直被游戏缠身不能自拔哈哈,但是游戏打多了真的是感觉整个人浮躁的不行,所以我现在要去游戏多写代码多看书,今天在博客园中看到一个前辈 ...
- (转)Java中equals和==的区别
java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号( ...
- C# 中 equals( ) 和 == 的区别和用法
Equals: 下面的语句中,x.y 和 z 表示不为 null 的对象引用. * 除涉及浮点型的情况外,x.Equals(x) 都返回 true. * x.Equals(y) 返回与 y.Equal ...
- Java 中 Equals和==的区别(转)
另外一篇参考: https://blog.csdn.net/striverli/article/details/52997927 在谈论equals和==的区别前,我们先简单介绍一下JVM中内存分配的 ...
- Java中equals和==的区别?为什么重写equals方法后,一定要重写hashCode方法?
首先明确一点,equals是方法,==是操作符. 1. 如果比较的是基本数据类型: 只讨论==,因为equals是不存在的,因为java中基本数据类型不能调用method的. 2. 如果比较的是引用类 ...
- java中equals和==的区别详解
java中的数据类型,可分为两类: 1.基本数据类型. byte,short,char,int,long,float,double,boolean这八大原始数据类型他们之间的比较,使用“==”,比较的 ...
- C#中equals和==的区别有哪些
本文导读:C# 中==是用来判断变量的值是否相等,相等返回true,不相等返回false.Equals是用来判断两个对象(除string类型外)是否相等,相等的 条件是:值,地址,引用全相等,因为St ...
- java中equals()和==的区别
java中的数据类型 基础数据类型 基础数据类型有byte.short.char.int.long.float.double.bool.String.除了 String 会比较地址,其它的基础类型的比 ...
随机推荐
- [LeetCode] 847. Shortest Path Visiting All Nodes 访问所有结点的最短路径
An undirected, connected graph of N nodes (labeled 0, 1, 2, ..., N-1) is given as graph. graph.lengt ...
- redis持久化方式与优缺点
Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化.redis支持四种持久化方式,一是 Snapshotting(快照)也是默认方式:二是Appen ...
- [转载]3.15 UiPath图片操作保存图片的介绍和使用
一.保存图像 (Save Image)的介绍 可以将图像保存到磁盘的一种活动 二.保存图像 (Save Image)在UiPath中的使用 1.打开设计器,在设计库中新建一个Sequence,为序列命 ...
- 第22课 weak_ptr弱引用智能指针
一. weak_ptr的概况 (一)weak_ptr的创建 1. 直接初始化:weak_ptr<T> wp(sp); //其中sp为shared_ptr类型 2. 赋值: wp1 = sp ...
- SQLserver 存储过程游标使用
ALTER PROCEDURE [dbo].[p_DeleteStretchData] ) , ) AS BEGIN ) ) declare @stretch_cursor cursor -- 声明游 ...
- What IS MPI
一.MPI message passing interface A specification for the developers and users of message passing libr ...
- AbstractExecutorService源码
public class RunnableFutureTask { static FinalizableDelegatedExecutorService executorService = (Fina ...
- Java 中的"+"号(加法和连接)
Java 中的"+"号(加法和连接) public class Test { public static void main(String[] args) { System.out ...
- 订单1:n支付单 设计讨论
方法一:订单1:1支付单,下单时生成1订单,并生成1支付单(这个支付单是微信需要的相关信息),设置超时时间2小时,如果订单超时,则提示用户,订单已超时,重新下单即可: 方法二:订单1:N支付单,下单时 ...
- JavaIO学习:序列化流
对象流 1.涉及到的类 ObjectInputStream 和 ObjectOutputStream 用于存储和读取基本数据类型数据或对象的处理流. 2.作用 ObjectOutputStream:内 ...