2017年9月11日 星期一

C# : 結構成員相等 Member Equal 的測試

我們知道,若由結構型別實例化出來的執行個體,若要使用該執行個體進行比較的話,預設會使用實值比較,也就是說,會針對該結構內的每個成員,進行比較。
若該結構內的資料成員全部都是屬於實值型別,與某些成員屬於參考型別的話,這樣會發生甚麼樣的情況呢?
在這裡,我們宣告了兩個結構與一個類別,進行這樣的測試。
  • MyStructString
    這個結構裡面的成員,全部都是實值型別
  • MyStructClass
    這個結構內,有一個成員的型別為 MyClass,這個成員的型別將會是參考型別
public struct MyStructString
{
    public int ID { get; set; }
    public string Name { get; set; }
    public MyStructString(int id, string name)
    {
        ID = id;
        Name = name;
    }
}
public class MyClass
{
    public int ID { get; set; }
    public MyClass(int id)
    {
        ID = id;
    }
}
public struct MyStructClass
{
    public int ID { get; set; }
    public MyClass MYClass { get; set; }
    public MyStructClass(int id, MyClass myClass)
    {
        ID = id;
        MYClass = myClass;
    }
}

進行測試

首先,實例化出兩個結構的物件,不過,這兩個結構的物件的資料成員都擁有一樣的值,這裡一個是 Int 型別 (ID),一個是字串型別(Name)。
經過使用物件的 Equals 方法來進行比對這兩個物件,得到的結果是相同的。
可是,在這裡,我們注意到了, Name 這個屬性的型別是字串,這是個參考型別,所以,底下的測試,我們將會建立另外一個類別,與 MyStructString 結構類似的成員,不過,我們把 Name 這個字串型別屬性,變更成為 MYClass 這個 MyClass 參考類別的屬性。
MyStructString myObject1 = new MyStructString(99, "C#");
MyStructString myObject2 = new MyStructString(99, "C#");
Console.WriteLine($"結構成員比較 {myObject1.Equals(myObject2)}");
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
執行結果為
結構成員比較 True
Press any key for continuing...
MyStructClass 這個結構類別中,有個參考型別的屬性,其型別為客製化的類別 MyClass,我們在建立這個兩個結構物件的時候,讓結構的成員都設定成為具有相同的值(不過,分別屬於不同的執行個體)。
當我們使用了結構物件的 Equals 方法進行比對的時候,卻得到不成立的答案。
可是,這個測試結構 MyStructClass 與前一個測試結構 MyStructString,裡面都會有一個參考型別,前者為 MyClass,後者為 string。同樣都是參考的類別型別,為什麼會得到不相同的結果呢?
這是因為, string 這個參考型別,由覆寫了 Equals 方法,當進行兩個 string 字串物件比較的時候,這些 string 所生成的物件,會根據物件內實際的字串內容進行比對,而不是使用參考來進行比對是否相等。
這樣就可以解釋,為什麼 MyStructClass 會得到 False 的結果,那是因為在 MyClass 沒有覆寫 Equals 這個方法,所以,當呼叫 Equals 方法的時候,會使用參考物件的參考值來進行比對,也就是當兩個參考都指向同一個物件的時候,才會得到 True 的結果。
MyStructClass mySCObject1 = new MyStructClass(66, new MyClass(168));
MyStructClass mySCObject2 = new MyStructClass(66, new MyClass(168));
Console.WriteLine($"結構成員比較 {mySCObject1.Equals(mySCObject2)}");
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
執行結果為
結構成員比較 False
Press any key for continuing...

沒有留言:

張貼留言