一次線上問題引發的對於C#中相等判斷的思考
線上報來一個問題,說使用者的資料丟失了。開發經過緊張的調查。終於找到了原因。
if (newData.GetValue(rowIndex) == oldData.GetValue(rowIndex)) { .................. } public object GetValue(string fieldName)) { ...............
return values[filedName]; //這是一個簡單型別: int,string }
問題出在了 if 中的比較上。 values[rowIndex] 中儲存的是一個整數,開發認為兩個整數比較實用 == 就可以了。
但是 values[rowIndex] 中的整數經過 GetValue返回後被作為 object 物件返回了,這時如果還使用 == 進行比較就會出現不等的情況。
我們來看一個更全面的例子:
static void Main(string[] args) { object value1 = new object(); object value2 = new object(); value1 = 2; value2 = 2; Console.WriteLine("value1 == value2 {0}", (value1 == value2).ToString()); Console.WriteLine("vvalue1.Equals(value2) {0}", value1.Equals(value2).ToString()); Console.WriteLine("Equals(value1, value2) {0}", Equals(value1, value2).ToString()); Console.WriteLine("ReferenceEquals(value1,value2) {0}", ReferenceEquals(value1,value2).ToString()); }
執行結果
value1 == value2 False
value1.Equals(value2) True
Equals(value1, value2) True
ReferenceEquals(value1,value2) False
如果我們將value1, value2 都定義為數字,但是一個是long,一個是uint.
static void Main(string[] args) { long value1 = 2; int value2 = 2; Console.WriteLine("value1 == value2 {0}", (value1 == value2).ToString()); Console.WriteLine("value1.Equals(value2) {0}", value1.Equals(value2).ToString()); Console.WriteLine("Equals(value1, value2) {0}", Equals(value1, value2).ToString()); Console.WriteLine("ReferenceEquals(value1,value2) {0}", ReferenceEquals(value1,value2).ToString()); }
看一下執行結果 ,使用 == ,和 value1.Equals 方法比較是相等的。
value1 == value2 True
value1.Equals(value2) True
Equals(value1, value2) False
ReferenceEquals(value1,value2) False
結合上面兩個例子,我們定義一個long 變數, 一個unit 變數, 給它們賦值之後,再將這兩個變數賦值給兩個object 物件。
static void Main(string[] args) { object value1 = new object(); object value2 = new object(); long lgval = 2; int ival = 2; value1 = lgval; value2 = ival; Console.WriteLine("lgval == ival {0}", (lgval == ival).ToString()); Console.WriteLine("value1 == value2 {0}", (value1 == value2).ToString()); Console.WriteLine("value1.Equals(value2) {0}", value1.Equals(value2).ToString()); Console.WriteLine("Equals(value1, value2) {0}", Equals(value1, value2).ToString()); Console.WriteLine("ReferenceEquals(value1,value2) {0}", ReferenceEquals(value1,value2).ToString()); }
可以看到,除去值型別 lgval 和 uval 相等外,其它都是不相等的。
lgval == uval True value1 == value2 False value1.Equals(value2) False Equals(value1, value2) False ReferenceEquals(value1,value2) False
是不是很抓狂? 到底什麼情況下相等?什麼情況下不等?我們先將上面的結果總結一下。
value1 和value2都是Object 物件 含有相同型別的值物件(int) 含有相同的值 |
value1 是long,value2 是 int 含有相同的值 |
value1 和value2都是Object 物件 含有不同型別的值物件(long,int) 含有相同的值 |
|
value1 == value2 |
false | true | false |
value1.Equals(value2) |
true | true | false |
Equals(value1, value2) |
true | false | false |
ReferenceEquals(value1,value2) |
false | false | false |
如果將一個值型別賦值給一個object 物件後,如何判斷相等? 微軟官方也沒有給出一個標準的說法。從測試的角度來看。
兩個比較的 object 中的內容如果型別相同,可以使用Equals 來進行比較。
不過我個人還是建議如果是比較值,還是轉換為對應的值型別進行比較,這樣比較清晰,不容易犯錯,大家也不用搞清楚 == 和 Equals 之前的細微差別。
ps: 如果object 的型別是 string , 上面的結果又會有所不同,有興趣的同學可以自己嘗試一下。