C#中Equals 与== 的区别
2021-02-11 14:16
这个问题听说是大公司面试都会问的问题,以前不怎么了解,好奇心勾引我来研究一下
首先从值类型分析,先写几句简单的代码供测试用,二行语句输出的都是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类型比较的是引用地址下的内容