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 , 上面的結果又會有所不同,有興趣的同學可以自己嘗試一下。
是否可以這樣理解,我們在int32 裝箱後的物件上呼叫Equals 方法,會走到Int32的Equals 方法上?因為看object 方法的Equals 並沒有看到這個邏輯。
-----------------------------------------------------------------------
object.cs
[__DynamicallyInvokable]
public virtual bool Equals(object obj)
{
return RuntimeHelpers.Equals(this, obj);
}
[__DynamicallyInvokable]
public static bool Equals(object objA, object objB)
{
if (objA == objB)
return true;
if (objA == null || objB == null)
return false;
return objA.Equals(objB);
}
-------------------------------------------------------------------
RuntimeHelper.cs
[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
public new static extern bool Equals(object o1, object o2);
Linux公社的RSS地址 :https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址:https://www.linuxidc.com/Linux/2019-01/1565.64htm