1. 程式人生 > >一次線上問題引發的對於C#中相等判斷的思考

一次線上問題引發的對於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 , 上面的結果又會有所不同,有興趣的同學可以自己嘗試一下。