C#中Equals 与== 的区别

2021-02-11 14:16

阅读:653

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

 

首先从值类型分析,先写几句简单的代码供测试用,二行语句输出的都是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,好长的一大段

 1       private unsafe static bool EqualsHelper(String strA, String strB)
 2         {
 3             Contract.Requires(strA != null);
 4             Contract.Requires(strB != null);
 5             Contract.Requires(strA.Length == strB.Length);
 6             //保存当前String长度
 7             int length = strA.Length;
 8             //固定住二个字符串的首字符地址
 9             fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
10             {
11                 //定义二个指针用来保存字符串首地址
12                 char* a = ap;
13                 char* b = bp;
14                 //下面判断是否是AMD64位系统,我这不是就往下执行
15                 // unroll the loop
16 #if AMD64
17                 // for AMD64 bit platform we unroll by 12 and
18                 // check 3 qword at a time. This is less code
19                 // than the 32 bit case and is shorter
20                 // pathlength
21 
22                 while (length >= 12)
23                 {
24                     if (*(long*)a     != *(long*)b) return false;
25                     if (*(long*)(a+4) != *(long*)(b+4)) return false;
26                     if (*(long*)(a+8) != *(long*)(b+8)) return false;
27                     a += 12; b += 12; length -= 12;
28                 }
29                 
30 #else           
31                 //A段感觉是多余的,直接执行B段就完事
32                 //判断字符串A长度是否大于10,为真的话每次读取四个字节进行比较
33                 //如果不相同就直接返回false,最后指针向后移动10个字节,长度减少10
34                 while (length >= 10)
35                 {
36                     if (*(int*)a != *(int*)b) return false;
37                     if (*(int*)(a+2) != *(int*)(b+2)) return false;
38                     if (*(int*)(a+4) != *(int*)(b+4)) return false;
39                     if (*(int*)(a+6) != *(int*)(b+6)) return false;
40                     if (*(int*)(a+8) != *(int*)(b+8)) return false;
41                     a += 10; b += 10; length -= 10;
42                 }
43 #endif
44 
45                 // This depends on the fact that the String objects are
46                 // always zero terminated and that the terminating zero is not included
47                 // in the length. For odd string sizes, the last compare will include
48                 // the zero terminator.
49 
50                 //B段
51                 //这里是前10个字节的匹配情况下,从+10开位置开始继续每四个字节的进行比较
52                 //只要不匹配,跳出循环,那长度肯定肯定不为0, 这里break也是多余,直接return false
53                 //如果所有字节都匹配,最终长度为0,跳出循环,返回真
54                 while (length > 0) 
55                 {
56                     if (*(int*)a != *(int*)b) break;
57                     a += 2; b += 2; length -= 2;
58                 }
59 
60                 return (length 0);
61             }
62         }

经过漫长的分析可以得出结论,== 与Equals比较的是每个字符,而并不是比较的引用地址

 

试试自定义的引用类型,创建一个类.先写几句简单的代码供测试用,二行语句输出的都是false

技术分享图片

说明自定义的引用类型 == 与Equals也是相同,比较的都是引用地址

 

结论就是不管是==还是Equals其结果都是相同的

当类型是值类型时,比较是数值

当类型是引用类型时,比较的是引用地址,除了String类型比较的是引用地址下的内容


评论


亲,登录后才可以留言!