C# 7个方法比较两个对象是否相等

2024-09-02 18:36

本文主要是介绍C# 7个方法比较两个对象是否相等,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

image

前言

在现实中的编程生活里,我们时常遇到一个棘手的问题:如何比较两个相同类型的对象是否 “相等”,比如在 ERP 系统中,企业的信息非常重要,每一次更新维护,都需要系统自动地详细记录更新前后企业不一致的信息、更新时间和更新人等等。

但是,直接比较通常只能告诉我们它们是否指向同一个内存地址,而不能告诉我们它们的内容是否一致,所以即使两个相同类型的对象的值都一致,程序还是偏偏说:“对不起,他们没关系!” 那我们应该怎么办呢?别急,接下来我们一起探索。

在 C# 中,要比较两个对象实例是否相等,有一些常用的方法。

比如实现 IEquatable<T> 接口、重写 Object.Equals 方法,或使用自定义比较逻辑等等。

以下是 7 种常用的方法:

1. 实现 IEquatable 接口

实现 IEquatable<T> 接口是一个好习惯,就像在你的小屋里挂上一个 “欢迎光临” 的牌子,让外界知道你准备好接受比较了,实现这个接口之后,你还可以创建更强类型的比较方法。

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 方法

这是老派的做法,但依然有效。

当你重写了 EqualsGetHashCode 方法后,你就能告诉对象们: “嘿,你们俩是一样的!” 。

如果你使用的是 .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. 利用匿名函数或 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 字符串再比较

如果你需要快速比较两个复杂对象,可以考虑把它们序列化成 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 字符串

需要注意的是,这种方法对于复杂类型或含有大量嵌套对象的情况,性能和效率可能比较差。

6. 直接比较

虽然说大多数情况,两个相同类型的对象之间不能直接比较,但 record 类型是个例外。

如果你使用的是 .NET 6 及之后的版本,并且对象的类型是 record 类型,那么恭喜你!

因为记录类型默认实现了 EqualsGetHashCode 方法,并且提供了 ==!= 运算符重载,使得比较变得非常简单

public record Test(int Id,string Name);// 创建两个 Test 对象
Test a = new Test(1, "test");
Test b = new Test(1, "test");// 比较两个对象是否相等
bool areEqual = a == b; // 返回 true

7. 使用第三方库

最后,当然不能错过各种强大的第三方库,它们就像是你编程生活中的 “金牌助手” ,如果你懒得自己动手造轮子,它们会是你的最佳选择,推荐几个我常用的库:

  • 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);
    

以上只是一些简单的例子,小伙伴们可以到这些第三方库的官网解锁更多使用姿势!

总结

比较对象是编程中的一项基本技能,它帮助我们维护数据的和谐,提升业务逻辑的效率,确保应用程序的正常运行,希望这 7 个方法能够让你在面对比较对象的任务时游刃有余!

记得在比较之前处理好 null 的情况,以免出现空引用异常哦!祝你编程愉快!

往期精彩

  1. 闲话 .NET(7):.NET Core 能淘汰 .NET FrameWork 吗?
  2. 常用的 4 种 ORM 框架(EF Core,SqlSugar,FreeSql,Dapper)对比总结

我是老杨,一个执着于编程乐趣、至今奋斗在一线的 10年+ 资深研发老鸟,是软件项目管理师,也是快乐的程序猿,持续免费分享全栈实用编程技巧、项目管理经验和职场成长心得。欢迎关注老杨的公众号,相互交流,共同进步!

这篇关于C# 7个方法比较两个对象是否相等的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1130749

相关文章

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int