[C#.NET] 利用序列化 比較兩物件是否相等
參考型別是不能直接拿來做相等判斷,假使我直接調用 object.Equals 方法,用來判斷兩物件裡的值是否相等。
程式碼如下:這樣寫只會得到 false
參考:http://www.dotblogs.com.tw/larrynung/archive/2009/10/21/11168.aspx
{
Person target = new Person()
{
Age = 18,
Address = "地球村",
Name = new Name("余", "小章"),
};
Person expected = new Person()
{
Age = 18,
Address = "地球村",
Name = new Name("余", "小章"),
};
if (expected.Equals(target))
{
MessageBox.Show("兩物件的值相等");
}
else
{
MessageBox.Show("兩物件的值不相等");
}
}
定義類別如下:
public class Name
{
public string FristName { get; set; }
public string LastName { get; set; }
public Name()
{
}
public Name(string frisName, string lastName)
{
this.FristName = frisName;
this.LastName = lastName;
}
}
[Serializable]
public class Person
{
public int Age { get; set; }
public string Address { get; set; }
public Name Name { get; set; }
}
到底要怎麼做才能比對兩個物件的值是否相等?我想這是很多人心中的疑惑。
解決方案:
假如我們要比較兩個物件,我們可以覆寫 object.Equals 方法,用來告知 CLR,想要比較兩個物件裡的什麼欄位。
http://msdn.microsoft.com/zh-tw/library/dd183752.aspx
http://msdn.microsoft.com/zh-tw/library/dd183755.aspx
http://www.dotblogs.com.tw/yc421206/archive/2012/05/25/72398.aspx
比如這樣寫:
{
if (this.Age != ((Person)obj).Age)
{
return false;
}
return true;
}
PS1.假若覆寫了 Equals 方法也別忘了處理 GetHashCode 方法。
{
return Age.GetHashCode() ^ Address.GetHashCode() ^ Name.FristName.GetHashCode() ^ Name.LastName.GetHashCode();
}
PS2.實作 GetHashCode 可參考以下規則:
http://www.dotblogs.com.tw/larrynung/archive/2009/12/16/12489.aspx
或是實作 IEqualityComparer 介面:
http://msdn.microsoft.com/zh-tw/library/system.collections.iequalitycomparer(v=vs.80).aspx
PS3.沒事的話不要覆寫它們兩個,有太多的功能會用到它們,若沒寫好可能會造成癱瘓。
這時,我需要每個欄位都比對正確,才算是相同的物件,若是按照上面的方式來做,可想而知 Equals 方法裡會有很多的判斷式,為了減少 Hard Code 的時間,在這裡提供利用序列化的技巧來處理。
程式碼如下:
public class Person
{
public int Age { get; set; }
public string Address { get; set; }
public Name Name { get; set; }
public override bool Equals(object obj)
{
var targetArray = getObjectByte(this);
var expectedArray = getObjectByte(obj);
var equals = expectedArray.SequenceEqual(targetArray);
return equals;
}
private byte[] getObjectByte(object model)
{
using (MemoryStream memory = new MemoryStream())
{
XmlSerializer xs = new XmlSerializer(model.GetType());
xs.Serialize(memory, model);
var array = memory.ToArray();
return array;
}
}
}
可以看到 Equals 方法裡,使用序列化將物件轉成Byte[],然後再比對兩物件的Byte[],這樣幫我們縮短不少 Hard Code 的時間,假使爾後類別新增欄位,也不必再另外處理它。
當然,也可以將它弄成擴充方法,讓所有的物件都享有這功能
{
public static bool EqualsObject(this object obj1, object obj2)
{
var targetArray = getObjectByte(obj1);
var expectedArray = getObjectByte(obj2);
var equals = expectedArray.SequenceEqual(targetArray);
return equals;
}
private static byte[] getObjectByte(object model)
{
using (MemoryStream memory = new MemoryStream())
{
XmlSerializer xs = new XmlSerializer(model.GetType());
xs.Serialize(memory, model);
var array = memory.ToArray();
return array;
}
}
}
如此一來便能比較兩個物件裡的值是否相等。
序列化相關應用:
[C#.NET] 利用序列化進行類別深複製- 余小章@ 大內殿堂- 點部落
[C#.NET] 物件oject/class 的加解密- 余小章@ 大內殿堂- 點部落
[C#.NET][Winform] 序列化表單 - 多國語言應用程式 / Form Serialize - Multiple Languages Application
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET