C#中實現(xiàn)比較兩個對象是否相等的7個方法總結(jié)
前言
在現(xiàn)實中的編程生活里,我們時常遇到一個棘手的問題:如何比較兩個相同類型的對象是否 “相等”,比如在 ERP 系統(tǒng)中,企業(yè)的信息非常重要,每一次更新維護,都需要系統(tǒng)自動地詳細記錄更新前后企業(yè)不一致的信息、更新時間和更新人等等。
但是,直接比較通常只能告訴我們它們是否指向同一個內(nèi)存地址,而不能告訴我們它們的內(nèi)容是否一致,所以即使兩個相同類型的對象的值都一致,程序還是偏偏說:“對不起,他們沒關(guān)系!” 那我們應(yīng)該怎么辦呢?別急,接下來我們一起探索。
在 C# 中,要比較兩個對象實例是否相等,有一些常用的方法。
比如實現(xiàn) IEquatable<T> 接口、重寫 Object.Equals 方法,或使用自定義比較邏輯等等。
以下是 7 種常用的方法:
1. 實現(xiàn) IEquatable 接口
實現(xiàn) IEquatable<T> 接口是一個好習(xí)慣,就像在你的小屋里掛上一個 “歡迎光臨” 的牌子,讓外界知道你準(zhǔn)備好接受比較了,實現(xiàn)這個接口之后,你還可以創(chuàng)建更強類型的比較方法。
public class Test : IEquatable<Test>
{
public int Id { get; set; }
public string Name { get; set; }
public bool Equals(Test other)
{
if (other == null)
return false;
return this.Id == other.Id && this.Name == other.Name;
}
public override bool Equals(object obj)
{
return Equals(obj as Test);
}
public override int GetHashCode()
{
return (Id, Name).GetHashCode(); // 可以使用 C# 7.3 中的元組
}
}
2. 重寫 Object.Equals 和 GetHashCode 方法
這是老派的做法,但依然有效。
當(dāng)你重寫了 Equals 和 GetHashCode 方法后,你就能告訴對象們: “嘿,你們倆是一樣的!” 。
如果你使用的是 .NET8 或更高版本時,你還可以使用 源生成器 (source generators) 特性幫助自動生成 Equals, GetHashCode 等常用方法,編程工作更輕松!
public class Test
{
public int Id { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
if (obj is Test other)
{
return this.Id == other.Id && this.Name == other.Name;
}
return false;
}
public override int GetHashCode()
{
return (Id, Name).GetHashCode();
}
}
3. 重載 == 操作符
有時候,我們更傾向于使用 == 操作符來比較對象,為了讓你的代碼看起來更加自然,不妨重載一下這個操作符吧!
注意,重載 == 操作符時,通常也要重載 != 操作符
public class Test
{
public int Id { get; set; }
public string Name { get; set; }
public static bool operator ==(Test left, Test right)
{
if (left is null && right is null) return true;
if (left is null || right is null) return false;
return left.Equals(right);
}
public static bool operator !=(Test left, Test right)
{
return !(left == right);
}
public override bool Equals(object obj)
{
return obj is Test other && Equals(other);
}
public override int GetHashCode()
{
return (Id, Name).GetHashCode();
}
}
4. 利用匿名函數(shù)或 Lambda 表達式
如果你只是偶爾需要比較兩個對象,Lambda 表達式是個不錯的選擇,簡單又直接,快速搞定一切:
Test A = new Test { Id = 1, Name = "Test" };
Test B = new Test { Id = 1, Name = "Test" };
bool areEqual = A.Id == B.Id && A.Name == B.Name; // 手動比較屬性
5. 序列化為 Json 字符串再比較
如果你需要快速比較兩個復(fù)雜對象,可以考慮把它們序列化成 JSON 字符串然后進行比較,這種方法雖然不是直接的對象比較方法,但簡單粗暴,在某些情況下能大顯身手。
序列化推薦使用 System.Text.Json(.NET 6 及之后的版本)或 Newtonsoft.Json(第三方庫)這兩個庫。
using System.Text.Json; var jsonA = JsonSerializer.Serialize(A); var jsonB = JsonSerializer.Serialize(B); bool areEqual = jsonA == jsonB; // 比較 JSON 字符串
需要注意的是,這種方法對于復(fù)雜類型或含有大量嵌套對象的情況,性能和效率可能比較差。
6. 直接比較
雖然說大多數(shù)情況,兩個相同類型的對象之間不能直接比較,但 record 類型是個例外。
如果你使用的是 .NET 6 及之后的版本,并且對象的類型是 record 類型,那么恭喜你!
因為記錄類型默認實現(xiàn)了 Equals 和 GetHashCode 方法,并且提供了 == 和 != 運算符重載,使得比較變得非常簡單
public record Test(int Id,string Name); // 創(chuàng)建兩個 Test 對象 Test a = new Test(1, "test"); Test b = new Test(1, "test"); // 比較兩個對象是否相等 bool areEqual = a == b; // 返回 true
7. 使用第三方庫
最后,當(dāng)然不能錯過各種強大的第三方庫,它們就像是你編程生活中的 “金牌助手” ,如果你懶得自己動手造輪子,它們會是你的最佳選擇,推薦幾個我常用的庫:
EqualityComparer,一個泛型類,可以用于比較兩個對象的相等性,例如:
bool areEqual = EqualityComparer<Test>.Default.Equals(A, B);
Objects Comparer,它允許逐個成員遞歸地比較對象,并為某些屬性、字段或類型定義自定義比較邏輯,例如:
var comparer = new ObjectsComparer<Test>; var test1 = new Test(1, "test"); var test2 = new Test(1, "test"); var isEqual = comparer.Compare(test1, test2); // 比較兩個對象 ......
Compare.NET Objects,可以更詳細地獲取兩個對象之間的差異,并記錄具體的差別,例如:
var test1 = new Test(1, "test");
var test2 = new Test(1, "test");
var propertyCount = 2;
CompareLogic compareLogic = new CompareLogic()
{
Config = new ComparisonConfig()
{
MaxDifferences = propertyCount //MaxDifferences的默認值是1
}
};
bool result = compareLogic.Compare(test1, test2).AreEqual;
Console.Write(result);
以上只是一些簡單的例子,小伙伴們可以到這些第三方庫的官網(wǎng)解鎖更多使用姿勢!
總結(jié)
比較對象是編程中的一項基本技能,它幫助我們維護數(shù)據(jù)的和諧,提升業(yè)務(wù)邏輯的效率,確保應(yīng)用程序的正常運行,希望這 7 個方法能夠讓你在面對比較對象的任務(wù)時游刃有余!
記得在比較之前處理好 null 的情況,以免出現(xiàn)空引用異常哦!
到此這篇關(guān)于C#中實現(xiàn)比較兩個對象是否相等的7個方法總結(jié)的文章就介紹到這了,更多相關(guān)C#比較兩個對象是否相等內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實現(xiàn)json格式數(shù)據(jù)解析功能的方法詳解
這篇文章主要介紹了C#實現(xiàn)json格式數(shù)據(jù)解析功能的方法,結(jié)合實例形式較為詳細的分析了C#解析json格式數(shù)據(jù)的具體操作步驟與相關(guān)注意事項,需要的朋友可以參考下2017-12-12
C#取得Web程序和非Web程序的根目錄的N種取法總結(jié)
C#取得Web程序和非Web程序的根目錄的N種取法,方便大家知道,有更好的方法,請說明2008-03-03
C#開發(fā)微信門戶及應(yīng)用(2) 微信消息處理和應(yīng)答
文章主要為大家詳細介紹了C#開發(fā)微信門戶及應(yīng)用第二篇,微信消息處理和應(yīng)答,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
總結(jié)C#刪除字符串?dāng)?shù)組中空字符串的幾種方法
C#中要如何才能刪除一個字符串?dāng)?shù)組中的空字符串呢?下面的文章會介紹多種方式來實現(xiàn)清除數(shù)組中的空字符串,以及在.net中將字符串?dāng)?shù)組中字符串為空的元素去除。2016-08-08
C#和vb.net實現(xiàn)PDF 添加可視化和不可見數(shù)字簽名
本文通過C#程序代碼展示如何給PDF文檔添加可視化數(shù)字簽名和不可見數(shù)字簽名。文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08

