了解更多關於 [Object.Equals Method]
了解更多關於 [C# 程式設計手冊]
在這裡,我們定義兩個結構
MyStruct
這個結構內,宣告了兩個屬性,並且透過了建構函式進行這兩個屬性的內容初始化。MyStructWithEqualOperator
這個結構內,同樣的,宣告了兩個屬性,並且透過了建構函式進行這兩個屬性的內容初始化。不過,這裡使用了多載運算子public static bool operator ==
與public static bool operator !=
的宣告,進行宣告了這個結構可以使用的新的==
/!=
運算子的處理邏輯。在==
運算子中,我們使用了結構物件(這裡使用的是 MyStructWithEqualOperator 型別的物件,而不是 object) 的 Equals 方法來進行兩個物件的比較。
public struct MyStruct
{
public int X { get; set; }
public int Y { get; set; }
public MyStruct(int x, int y)
{
X = x;
Y = y;
}
}
public struct MyStructWithEqualOperator
{
public int X { get; set; }
public int Y { get; set; }
public MyStructWithEqualOperator(int x, int y)
{
X = x;
Y = y;
}
public static bool operator ==(MyStructWithEqualOperator c1, MyStructWithEqualOperator c2)
{
return c1.Equals(c2);
}
public static bool operator !=(MyStructWithEqualOperator c1, MyStructWithEqualOperator c2)
{
return !c1.Equals(c2);
}
}
另外,我們宣告了類別
MyClass
,這個類別如同上述的結構一樣,有兩個屬性,可以透過建構式來進行初始化。public class MyClass
{
public int X { get; set; }
public int Y { get; set; }
public MyClass(int x, int y)
{
X = x;
Y = y;
}
}
進行測試 類別物件比較
首先我們要進行的測試為類別的物件比較,在這裡,我們產生兩個類別物件,這兩個物件擁有同樣的屬性值(這兩個屬性屬於 int 的型別),不過,這兩個物件在堆積(Heap)是分別佔據不同的記憶體空間,也可以說,這兩個物件變數分別指向了兩個不同實體。相關測試的程式碼如下所示。
Console.WriteLine("參考型別的物件比較");
MyClass classObject1 = new MyClass(10, 20);
MyClass classObject2 = new MyClass(10, 20);
MyClass classObject3;
classObject3 = classObject2;
Console.WriteLine($"classObject1==classObject2 is {classObject1 == classObject2}");
Console.WriteLine($"classObject1.Equals(classObject2) is {classObject1.Equals(classObject2)}");
Console.WriteLine($"object.Equals(classObject1, classObject2) is {object.Equals(classObject1, classObject2)}");
Console.WriteLine($"object.ReferenceEquals(classObject1, classObject2) is {object.ReferenceEquals(classObject1, classObject2)}");
Console.WriteLine("比較參考到同一個實體物件");
Console.WriteLine($"classObject3==structObject2 is {classObject3 == classObject2}");
Console.WriteLine($"classObject3.Equals(classObject2) is {classObject3.Equals(classObject2)}");
Console.WriteLine($"object.Equals(classObject3, classObject2) is {object.Equals(classObject3, classObject2)}");
Console.WriteLine($"object.ReferenceEquals(classObject3, classObject2) is {object.ReferenceEquals(classObject3, classObject2)}");
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
接著,我們進行了底下的測試,這個是關於兩個不同參考物件(但是成員屬性內容相同)的比較
- classObject1==classObject2這裡使用了靜態運算子方法來進行這兩個不同實體比較,因為預設為參考比較,所以得到的結果為 False。
- classObject1.Equals(classObject2)這裡使用物件本身的 Equals 方法來進行不同實體物件比較,因為預設為參考比較,所以得到的結果為 False。
- object.Equals(classObject1, classObject2)這裡使用最上層類別,object 的 Equals 靜態方法來進行不同實體物件比較,因為預設為參考比較,所以得到的結果為 False。
- object.ReferenceEquals(classObject1, classObject2)這裡使用最上層類別,object 的 ReferenceEquals 靜態方法來進行不同實體物件比較,所以得到的結果為 False。
這裡是這個測試的執行結果
參考型別的物件比較
structObject1==structObject2 is False
classObject1.Equals(classObject2) is False
object.Equals(classObject1, classObject2) is False
object.ReferenceEquals(classObject1, classObject2) is False
然後,我們進行了底下的測試,這個是關於兩個相同參考物件的比較,我們使用敘述
classObject3 = classObject2;
將 classObject3 與 classObject2 兩個物件變數設定成為參考到同一個物件實體。- classObject3==structObject2這裡使用了靜態運算子方法來進行這兩個相同實體比較,因為預設為參考比較,所以得到的結果為 True。
- classObject3.Equals(classObject2)這裡使用物件本身的 Equals 方法來進行相同實體物件比較,因為預設為參考比較,所以得到的結果為 True。
- object.Equals(classObject3, classObject2)這裡使用最上層類別,object 的 Equals 靜態方法來進行相同實體物件比較,因為預設為參考比較,所以得到的結果為 True。
- object.ReferenceEquals(classObject3, classObject2)這裡使用最上層類別,object 的 ReferenceEquals 靜態方法來進行相同實體物件比較,所以得到的結果為 True。
這裡是這個測試的執行結果
比較參考到同一個實體物件
classObject3==structObject2 is True
classObject3.Equals(classObject2) is True
object.Equals(classObject3, classObject2) is True
object.ReferenceEquals(classObject3, classObject2) is True
進行測試 結構物件比較
現在,我們要來測試結構的物件比較,在這裡,我們使用建構式,建立了兩個結構物件。
Console.WriteLine("結構型別的物件比較");
MyStruct structObject1 = new MyStruct(10, 20);
MyStruct structObject2 = new MyStruct(10, 20);
MyStruct structObject3;
structObject3 = structObject2;
//Console.WriteLine($"structObject1==structObject2 is {structObject1 == structObject2}");
Console.WriteLine($"structObject1.Equals(structObject2) is {structObject1.Equals(structObject2)}");
Console.WriteLine($"object.Equals(structObject1, structObject2) is {object.Equals(structObject1, structObject2)}");
Console.WriteLine($"object.ReferenceEquals(structObject1, structObject2) is {object.ReferenceEquals(structObject1, structObject2)}");
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
接著,我們進行了底下的測試,這個是關於兩個不同參考物件(但是成員屬性內容相同)的比較
- structObject1==structObject2當您使用這個敘述的時候,Visual Studio 會回報您有錯誤產生。
錯誤 CS0019 運算子 '==' 不可套用至類型為 'MyStruct' 和 'MyStruct' 的運算元 ObjectEqual
所以,若您沒有做任何多載 == 運算子的程式碼,您是無法在客製化結構中,使用這個運算子。 - structObject1.Equals(structObject2)這裡使用物件本身的 Equals 方法來進行不同實體物件比較,因為預設為實值比較,所以會針對該結構內的成員進行實際擁有值的比較,所以得到的結果為 True
- object.Equals(structObject1, structObject2)這裡使用最上層類別,object 的 Equals 靜態方法來進行不同實體物件比較,因為預設為實值比較,所以會針對該結構內的成員進行實際擁有值的比較,所以得到的結果為 True
- object.ReferenceEquals(structObject1, structObject2)這裡使用最上層類別,object 的 ReferenceEquals 靜態方法來進行不同實體物件比較,所以得到的結果為 False。
這裡是這個測試的執行結果
結構型別的物件比較
structObject1.Equals(structObject2) is True
object.Equals(structObject1, structObject2) is True
object.ReferenceEquals(structObject1, structObject2) is False
進行測試 結構物件比較(有多載 == != 運算子)
在上面的測試中,我們看到了,結構預設無法使用 == 或者 != 運算子來進行物件內容比較,所以,在這個測試中,我們使用了客製化結構
MyStructWithEqualOperator
,在這個結構內,有多載 == != 運算子的宣告,讓我們可以在結構的 == 與 != 運算子,來進行物件的比較。Console.WriteLine("結構型別的物件比較(有多載等於與不等於的運算子)");
MyStructWithEqualOperator structWithEqualOperatorObject1 = new MyStructWithEqualOperator(10, 20);
MyStructWithEqualOperator structWithEqualOperatorObject2 = new MyStructWithEqualOperator(10, 20);
MyStructWithEqualOperator structWithEqualOperatorObject3;
structWithEqualOperatorObject3 = structWithEqualOperatorObject2;
Console.WriteLine($"structWithEqualOperatorObject1==structWithEqualOperatorObject2 is {structWithEqualOperatorObject1 == structWithEqualOperatorObject2}");
Console.WriteLine($"structWithEqualOperatorObject1.Equals(structWithEqualOperatorObject2) is {structWithEqualOperatorObject1.Equals(structWithEqualOperatorObject2)}");
Console.WriteLine($"object.Equals(structWithEqualOperatorObject1, structWithEqualOperatorObject2) is {object.Equals(structWithEqualOperatorObject1, structWithEqualOperatorObject2)}");
Console.WriteLine($"object.ReferenceEquals(structWithEqualOperatorObject1, structWithEqualOperatorObject2) is {object.ReferenceEquals(structWithEqualOperatorObject1, structWithEqualOperatorObject2)}");
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
經過多載 == != 運算子之後,結構所產生的執行個體,就可以進行使用這兩個運算子了
結構型別的物件比較(有多載等於與不等於的運算子)
structWithEqualOperatorObject1==structWithEqualOperatorObject2 is True
structWithEqualOperatorObject1.Equals(structWithEqualOperatorObject2) is True
object.Equals(structWithEqualOperatorObject1, structWithEqualOperatorObject2) is True
object.ReferenceEquals(structWithEqualOperatorObject1, structWithEqualOperatorObject2) is False