这个问题听说是大公司面试都会问的问题,以前不怎么了解,好奇心勾引我来研究一下

首先从值类型分析,先写几句简单的代码供测试用,二行语句输出的都是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 与== 的区别的更多相关文章

  1. java中equals和==的区别 (转)

    java中equals和==的区别  值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...

  2. 【转】Java中equals和==的区别

    [转]Java中equals和==的区别 java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boole ...

  3. C#中 Equals和= =的区别

    C#中 Equals和= =的区别 前言:最近感觉技术进步实在是太慢,一直被游戏缠身不能自拔哈哈,但是游戏打多了真的是感觉整个人浮躁的不行,所以我现在要去游戏多写代码多看书,今天在博客园中看到一个前辈 ...

  4. (转)Java中equals和==的区别

    java中的数据类型,可分为两类:  1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean    他们之间的比较,应用双等号( ...

  5. C# 中 equals( ) 和 == 的区别和用法

    Equals: 下面的语句中,x.y 和 z 表示不为 null 的对象引用. * 除涉及浮点型的情况外,x.Equals(x) 都返回 true. * x.Equals(y) 返回与 y.Equal ...

  6. Java 中 Equals和==的区别(转)

    另外一篇参考: https://blog.csdn.net/striverli/article/details/52997927 在谈论equals和==的区别前,我们先简单介绍一下JVM中内存分配的 ...

  7. Java中equals和==的区别?为什么重写equals方法后,一定要重写hashCode方法?

    首先明确一点,equals是方法,==是操作符. 1. 如果比较的是基本数据类型: 只讨论==,因为equals是不存在的,因为java中基本数据类型不能调用method的. 2. 如果比较的是引用类 ...

  8. java中equals和==的区别详解

    java中的数据类型,可分为两类: 1.基本数据类型. byte,short,char,int,long,float,double,boolean这八大原始数据类型他们之间的比较,使用“==”,比较的 ...

  9. C#中equals和==的区别有哪些

    本文导读:C# 中==是用来判断变量的值是否相等,相等返回true,不相等返回false.Equals是用来判断两个对象(除string类型外)是否相等,相等的 条件是:值,地址,引用全相等,因为St ...

  10. java中equals()和==的区别

    java中的数据类型 基础数据类型 基础数据类型有byte.short.char.int.long.float.double.bool.String.除了 String 会比较地址,其它的基础类型的比 ...

随机推荐

  1. [LeetCode] 731. My Calendar II 我的日历之二

    Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event w ...

  2. cocos: RenderTexture 合并精灵图片

    var render = new cc.RenderTexture(730, 450); //创建渲染纹理对象,并数字确定宽度 render.begin(); var sp1 = cc.Sprite. ...

  3. java web开发入门十二(idea创建maven SSM项目需要解决的问题)基于intellig idea(2019-11-09 11:23)

    一.spring mvc action返回string带双引号问题 解决方法: 在springmvc.xml中添加字符串解析器 <!-- 注册string和json解析适配器 --> &l ...

  4. win10配置jdk1.8环境变量

    1,安装好jdk之后,目录如下 2,右键计算机 - 属性 - 高级系统设置 3,环境变量 4,新增系统变量JAVA_HOME,输入内容D:\work\Program Files\Java\jdk1.8 ...

  5. python运维开发常用模块(四)文件对比模块difflib

    1.difflib介绍 difflib作为 Python的标准库模块,无需安装,作用是对比文本之间的差异,且支持 输出可读性比较强的HTML文档,与Linux下的diff命令相似.我们可以 使用dif ...

  6. 在Azure DevOps Server (TFS)中实现VUE项目的自动打包

    概述 Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的渐进式框架.由于它在数据绑定.页面展示和使用简单方面有很大的优势,逐渐被越来越多的前端开发团队使用.本文 ...

  7. 文件上传之靶场upload-labs (11-20)

    第十一关 strrpos() 函数查找字符串在另一字符串中最后一次出现的位置 substr() 函数返回字符串的一部分 文件保存的方式是上传路径+随机时间+截取的文件后缀 其中上传路径可控,可以利用这 ...

  8. PHP 命名空间笔记

    PHP 命名空间笔记 1.php文件代码如下<pre><?php//我用这样的命名空间表示处于blog下的article模块namespace Blog\Article; class ...

  9. (算法)LeetCode刷题

    LeetCode 56 合并区别 Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18]. 关键就是a[1]>=b[0] 也就 ...

  10. kubernetes使用阿里云cpfs持久存储

    目录 简介 安装cpfs客户端 kubernetes使用cfs作为持久存储 简介 cpfs的具体介绍可参考这里: https://help.aliyun.com/document_detail/111 ...