[英]How do I check if two Objects are equal in terms of their properties only without breaking the existing Object.Equals()?
基本上, GethashCode 是不同的,即使它們包含相同的屬性值......那么為什么默認返回差異哈希碼?
public class User
{
public Int32 Id { get; set; }
public String Username { get; set; }
}
User a = new User();
a.Id = 1;
a.Username = "Hello";
User b = new User();
b.Id = 1;
b.Username = "Hello";
Console.WriteLine("Hash A: {0} | Hash B: {1}", a.GetHashCode(), b.GetHashCode());
//Hash A: 37121646 | Hash B: 45592480 <-- these values change each time I rerun the app?
有沒有更合適的方法來實現它,這樣我就不會破壞 Object.Equals 對我的對象的工作方式,但仍然能夠根據參數值進行我自己的相等性檢查?
我問的原因是因為我有一項服務: SynchronizeUsers()
,它下載一組用戶。 與其清除我的用戶緩存,我寧願只更新需要更新的用戶,刪除同步所說的用戶,然后添加新用戶。 但是,我不能只對這些對象執行 Object.Equals() 。
回答太晚了,但有人可能會在這里結束,我需要知道我的想法是對還是錯。 如果嚴格考慮值,那么為什么不將對象設為 JSON 並比較 JSON 字符串呢? 喜歡:
if (JsonConvert.SerializeObject(obj1) == JsonConvert.SerializeObject(obj2)) continue;
如果您安裝了 ReSharper(這是值得的!),那么您所要做的就是:
Alt+Insert
在課堂內使用光標。 部分類有利於隱藏樣板。
它將自動為每個屬性實現相等性檢查。
(使用 Ctrl+A 選擇所有屬性,您可以使用空格檢查所有屬性!)
您是否嘗試過實現自己的 IEqualityComparer? 您可以將其傳遞給 .Equals() 重載以定義您自己的自定義相等邏輯,如
用戶 A = 用戶 B,即使它們是不同的實例,如果屬性 x、y、z 相同。
看到這個: MSDN
編輯:我應該寫你可以實例化你的 EqualityComparer 並將兩個實例傳遞給它的 Equals() 方法並獲得一個布爾值。 基本控制台應用程序...將顯示真、假、假。 事情是微不足道的,具有所示的兩個屬性。
var comparer = new ThingEqualityComparer();
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, new Thing() { Id = 1, Name = "1" }));
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, new Thing() { Id = 2, Name = "2" }));
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, null));
class ThingEqualityComparer : IEqualityComparer<Thing>
{
public bool Equals(Thing x, Thing y)
{
if (x == null || y == null)
return false;
return (x.Id == y.Id && x.Name == y.Name);
}
public int GetHashCode(Thing obj)
{
return obj.GetHashCode();
}
}
建議在覆蓋 GetEquals() 時覆蓋 GetHashCode()。
http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx
例如
public override int GetHashCode()
{
return this.Username.GetHashCode() * this.Id;
}
這是一個不需要類中的任何自定義邏輯並使用泛型來確保兩個參數(obj1 和 obj2)在編譯時是相同類型的解決方案:
public static class ObjectComparerUtility
{
public static bool ObjectsAreEqual<T>(T obj1, T obj2)
{
var obj1Serialized = JsonConvert.SerializeObject(obj1);
var obj2Serialized = JsonConvert.SerializeObject(obj2);
return obj1Serialized == obj2Serialized;
}
}
用法:
var c1 = new ConcreteType { Foo = "test1" };
var c2 = new ConcreteType { Foo = "test1" };
var areEqual = ObjectComparerUtility.ObjectsAreEqual(c1, c2);
Assert.IsTrue(areEqual);
為什么不編寫自己的 Equality 方法? IE,
User a = new User();
a.Id = 1;
a.Username = "Hello";
User b = new User();
b.Id = 1;
b.Username = "Hello";
a.IsEqualTo(b);
其中 IsEqualTo 在您的用戶類中定義為:
Public bool IsEqualTo(user compareTo)
{
return (UserName == compareTo.UserName && Id == compareTo.Id);
}
添加一個方法:
public class User
{
public int UserID { get; set; }
public bool IsUser(object obj)
{
return (obj is User && ((User)obj).UserID == this.UserID);
}
}
如果您只想對事物進行散列,請考慮使用擴展方法來生成散列。
public static int GenerateHash(this User myUser){
return myUser.UserName.GetHashCode() ^ ... other properties....
}
然后在您的代碼中,您可以執行以下操作:
Console.WriteLine("Hash A: {0} | Hash B: {1}", a.GenerateHash(), b.GenerateHash());
這將使所有內容完好無損,並且不應破壞其他任何內容。 如果您正在尋找一種比較對象的方法,您可以使用擴展方法來做同樣的事情:
public static int AreEqual(this User myUser, User someOther){
return myUser.UserName == someOther.UserName && ... other properties.
}
用法如下:
if(a.AreEqual(b)){
// these are equal have fun.
}
字符串數組是比較的排除列表。 它使用反射但性能非常好。 請檢查 apache commons lang 3 庫
CompareToBuilder.reflectionCompare(arg0, arg1, new String[]{"UID", "uidcount"})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.