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] 905. Sort Array By Parity 按奇偶排序数组
Given an array A of non-negative integers, return an array consisting of all the even elements of A, ...
- 基于Redis实现分布式定时任务调度
项目开发过程中,难免会有许多定时任务的需求进来.如果项目中还没有引入quarzt框架的情况下,我们通常会使用Spring的@Schedule(cron="* * * * *")注解 ...
- react 16 Hooks渲染流程
useState react对useState进行了封装,调用了mountState. function useState<S>( initialState: (() => S) | ...
- 五年微软DevOps MVP (也称TFS MVP)
笔者有幸第五次被微软授予MVP称号,高兴之余,在这里简单的介绍一下MVP的基本情况: 谁是 MVP? Microsoft 最有价值专家 (MVP) 是热情地与社区分享知识的技术专家.他们总是处于&qu ...
- 使用VUECLI3
$ yarn global add @vue/cli // OR $ npm install @vue/cli -g 然后在加入下面的代码 $ vue create my-app $ cd my-ap ...
- python之lambda、filter、map、reduce的用法说明(基于python2)
python中有一些非常有趣的函数,面试的时候可能会遇到.今天也来总结一下,不过该类的网上资料也相当多,也没多少干货,只是习惯性将一些容易遗忘的功能进行整理. lambda 为关键字.filter,m ...
- 在Linux上利用curl 命令模拟 HTTP GET/POST 请求
本文系转载,原文地址:https://www.cnblogs.com/alfred0311/p/7988648.html 序言 在 Linux 操作系统上对后端程序进行测试的时候,需要进行模拟连接或者 ...
- Docker安装和上传容器
安装Docker Requirements for Mac(硬件要求): Mac的硬件必须是2010或者更新的,需要支持memory management unit(MMU) virtualizait ...
- Redis学习之intset整数集合源码分析
1.整数集合:整数的集合,升序排序,无重复元素 2.整数集合intset是集合键的底层实现之一,当一个集合只包含整数值的元素,并且这个集合的元素数量不多时,redis会使用整数集合作为集合键的底层实现 ...
- Rider 中无法显示DataTable,VS2019的.netCore才有DataTable可视化工具(4)
如下图在vs2017中是这样的 在2019中是可以直接看的 在Rider中无论什么项目都不支持.