這個問題聽說是大公司面試都會問的問題,以前不怎么了解,好奇心勾引我來研究一下
首先從值類型分析,先寫幾句簡單的代碼供測試用,二行語句輸出的都是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類型比較的是引用地址下的內容