理解CSharp 语言中相等Equality 和唯一 Identity

C# HashCode.Combine 使用详解 阅读详情

c#有一个“Equals”方法,可以用来比较两个对象。我将试着用例子来解释等式和同一性的概念。

  1. namespace TestEqualityDemo
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. TestEquality test1 = new TestEquality();
  8. test1.FirstName = "Tom";
  9. test1.FirstName = "Cruise";
  10. TestEquality test2 = new TestEquality();
  11. test2.FirstName = "Tom";
  12. test2.FirstName = "Cruise";
  13. TestEquality test3 = test2;
  14. bool areEqual = test1.Equals(test2);
  15. System.Console.WriteLine("Are test1 and test2 are Equal:" + areEqual);
  16. areEqual = test2.Equals(test3);
  17. System.Console.WriteLine("Are test2 and test3 are Equal:" + areEqual);
  18. System.Console.ReadLine();
  19. }
  20. }
  21. class TestEquality
  22. {
  23. public string FirstName { get; set; }
  24. public string LastName { get; set; }
  25. }
  26. }

输出:

  1. Are test1 and test2 Equal:False
  2. Are test2 and test3 Equal:True

在上面的例子中

即使test1和test2包含FirstName和LastName的值相同,“Equals”方法也返回False。这是因为Equals方法的默认实现不检查是否相等;它检查Identity(对象引用地址)。这意味着test1和test2必须引用完全相同的对象,然后只有它返回True,否则,它将返回False。

当test2和test3引用相同的对象时,它返回True。根据上面的程序,我们可以得出等号的默认实现,这意味着只有当两个变量指向同一个对象时,它才会返回True。

然后,出现了如何在c#中检查等式的问题,答案是覆盖Equals方法的默认实现。

这里是Equals方法的默认实现。

  1. public virtual bool Equals(Object obj)
  2. {
  3. //If both the references points to the same object then only return true
  4. if (this == obj)
  5. {
  6. return true;
  7. }
  8. return false;
  9. }

必须考虑以下几点来覆盖Equals方法,

如果obj参数为空,则返回false

如果this和obj引用相同的对象,则返回True。这可以在与许多字段进行比较时提高性能

如果this和obj指的是不同的类型,则返回False,因为没有必要比较不同类型的对象;例如,如果我们比较一个字符串对象和DateTime对象,因为它们在任何情况下都不相等。

将该对象的每个字段与obj对象的相应字段进行比较。

最后,调用基类=方法。

以上是重写Equals方法进行比较的最佳步骤。

让我们为TestEquality类实现Equals方法:

  1. namespace TestEqualityDemo
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. TestEquality test1 = new TestEquality();
  8. test1.FirstName = "Tom";
  9. test1.FirstName = "Cruise";
  10. TestEquality test2 = new TestEquality();
  11. test2.FirstName = "Tom";
  12. test2.FirstName = "Cruise";
  13. TestEquality test4 = new TestEquality();
  14. test2.FirstName = "Will";
  15. test2.FirstName = "Smith";
  16. TestEquality test3 = test2;
  17. bool areEqual = test1.Equals(test2);
  18. System.Console.WriteLine("Are test1 and test2 Equal:" + areEqual);
  19. areEqual = test2.Equals(test3);
  20. System.Console.WriteLine("Are test2 and test3 Equal:" + areEqual);
  21. System.Console.ReadLine();
  22. areEqual = test2.Equals(test4);
  23. System.Console.WriteLine("Are test2 and test4 Equal:" + areEqual);
  24. System.Console.ReadLine();
  25. }
  26. }
  27. class TestEquality
  28. {
  29. public string FirstName { get; set; }
  30. public string LastName { get; set; }
  31. public override bool Equals(System.Object obj)
  32. {
  33. //If the obj argument is null return false
  34. if (obj == null)
  35. return false;
  36. //If both the references points to the same object then only return true
  37. if (this == obj)
  38. return true;
  39. //If this and obj are referring to different type return false
  40. if (this.GetType() != obj.GetType())
  41. return false;
  42. //Compare each field of this object with respective field of obj object
  43. TestEquality test = (TestEquality)obj;
  44. if (this.FirstName == test.FirstName &&
  45. this.LastName == test.LastName)
  46. {
  47. return true;
  48. }
  49. return false;
  50. }
  51. }
  52. }

输出:

  1. Are test1 and test2 Equal:True
  2. Are test2 and test3 Equal:True
  3. Are test2 and test4 Equal:False

在上面的程序中,

test1和test2的所有字段都相等,所以Equals方法返回true。

test2和test3引用同一个对象,因此它也会返回false。

在test2和test4中,如果FirstName和LastName的值不同,则返回false

重写的Equals方法必须遵循下面的规则:

=必须是自反的,也就是x.Equals(x)必须返回true。

=必须是对称的,即 x.Equals(y)必须返回与 y.Equals(x)相同的值

等号必须是传递i。如果x.Equals(y) 返回true, y.Equals(z) 返回true,那么x.Equals(z)必须返回true。

如果重写的Equals方法不遵循上述规则,那么您的应用程序可能会中断或产生意外结果。

另外,在C#里为什么重载了Equals()就要重载GetHashCode()?发现如果只重载Equals的话,编译器会给一个警告:

warning CS0659: 'UseCom.Program.b' overrides Object.Equals(object o) but does not override Object.GetHashCode()

在解释这个问题之前需要先把Equals()和GetHashCode()方法进行深入了解。

首先先谈一下Equals()这个方法:

Equals()方法,来自于Object,是我们经常需要重写的方法。此方法的默认实现大概是这样的:

public virtual bool Equals(object obj){  if(obj==null) return false;  if(GetType() != obj.GetType()) return false;  return true;}

在很多地方都是特殊处理的,此处就不做深究了。

Ps:按Jeffrey Richter的说法,在值类型使用Equals()时,因为Equals()使用了反射,在比较时会影响效率。

说完Equals()后再来聊一聊GetHashCode()。

其实GetHashCode()在操作值类型的时候也是被System.ValueType()重写的。经过楼主测试的几个常用值类型来看,值类型的GetHashCode()基本都是原值输出(特指整数,Int32除外),真实性有待验证。

结果如下:

理解CSharp 语言中相等Equality 和唯一 Identity

说完值类型,说一下引用类型,先看下面这张运行结果:

理解CSharp 语言中相等Equality 和唯一 Identity

从上图的结果可以看出,虽然string是引用类型,但是只要值一样,返回的HashCode也是一样的,这取决于它的特殊性。而我们自己写的类型Coordinates同样的值但返回的HashCode却不一样,我们可以简单的理解为是coor1与coor2的内存地址不同,所以CLR认为它们是不一样的。

Ps:在程序的生命周期中,相同的对象、变量返回的HashCode是相同的,并且是唯一的。但是绝对不允许做持久性存储,程序一旦结束并重新启动后,同样的对象无法获得上次程序运行时的HashCode。

了解了两个方法后,开始今天的重点话题。

其实在上面的两个对象中(coor1、coor2),coor1.Equals(coor2)的返回结果为false(因为内存地址不同),如果我们想让它们的返回结果为true的话,只能重写Equals方法(如下图)。

理解CSharp 语言中相等Equality 和唯一 Identity

重点来了,重写完Equals以后,vs发出了警告,虽然程序猿从来都是无视警告的,但这个警告确实有必要了解一下,先来看下面这三段代码。

代码段一、二:

理解CSharp 语言中相等Equality 和唯一 Identity

代码段三:

理解CSharp 语言中相等Equality 和唯一 Identity

看完这三段代码,应该就理解为什么要重写Equal时有必要重写GetHashCode了。

当然,如果你没打算在代码中使用Dictionary或HashTable就无所谓写不写了,换句话说,如果要把引用类型做为Dictionary或HashTable的key使用时,必须重写这两个方法。

。其结果就是,存储的时候你可能任性的存,在取值的时候就是你哭着找不着娘了。

好了,说了这么多你应该对这两个方法有了重新的认识了吧。如果还是不明白的话,用代码实现一下,保准明白。

http://www.cnblogs.com/xiaochen-vip8/articles/5506478.html

C#中equals和==的差异及使用方式 通过调用equals方法,我们可以比较对象的内容,equals结果为false。最后,通过使用==操作符,我们比较了两个对象的引用,doubleEqualsResult结果为false。如果希望比较对象的内容而不是引用,就需要在自定义类中重写equals方法,并根据需要实现自定义的相等性比较逻辑。对于引用类型,==操作符比较的是对象的引用,对于值类型,==操作符比较的是值本身。在上面的示例中,我们重写了Person类的equals方法,通过比较Name和Age属性的值来判断两个Person对象是否相等。 阅读详情

相关推荐

步进电机励磁模式

1. 励磁模式 步进电机的基本操作模式称为 励磁模式,能够使步进电机工作在全步模式,半步模式和微步模式,其中微步模式能够有效的降低步进电机相电流的噪声,能够改善步进电机固有的噪声震动问题。下面将介绍 3 种励磁模式。 2. 全步励磁模式 所谓全步模式,就是依据电机固有结构设计固定的步距角工作,一个电脉冲,步进电机前进一个步距角。这个步距角使电机设计结构所决定的,也可以理解为电机以最大的步距角旋转。 3. 半步励磁模式 半步模式是以电机固有的结构决定的步距角的一半角度进行步进旋转。如下图所示,步进

zhbi98 的技术 Blogs 5548

CSharp的4种相等判断形式

C#语言中,对于变量相等的判断有4中形式,2个静态的object类的方法:ReferenceEquals(obj1,boj2)和Equals(obj1,obj2),还有实例方法Equals(),以及重载运算符号==。 (1)ReferenceEquals,看名字就知道比较的是2个变量的引用类型,所以很显然2个值类型永远都会返回false,就算是值类型变量自身相比,也返回f...

weixin_34404393的博客 1232

图像去雾常见数据集

上述数据集涵盖了室内、室外、真实和合成等多种场景,可以满足不同研究需求。在选择数据集时,建议根据具体任务的应用场景和目标选择合适的数据集,例如真实雾天图像适合模型的实际应用验证,而合成数据则适合模型的快速迭代和训练。希望本文能为从事图像去雾研究的朋友提供一些帮助!

m0_68604571的博客 6334

[C#] 每个 C# 开发人员都应该知道的事情#1:hash codes (哈希码)

译者总结:HashCode是为了给这个对象一个独一无二的id。让对象在哈希表内均匀的分布,使查找时,速度更快作为一名 C# 开发人员,显然需要掌握很多技能才能发挥作用:语言语法、框架类、第三方库、数据库、正则表达式、HTTP 协议等。

unity尧明的博客 1126

python:numpy分享(保姆级教程)

创建数组:array和ndarray、rand()、randn()、arange()、randint()、uniform()astype()基础函数:ceil()、floor()、rint()、argmax()、argmin()、cumsum()、cumprod()numpy 是数据分析必不可少的第三方库,具有高性能的特点,多用于做数组分析。内置函数:ceil()、floor()、rint()主要用于数组计算,支持多维数组。array和ndarray。比较函数:all、any。去重函数:unique。

sulin123123的博客 1730

光模块的封装工艺有哪些?

COB封装传统的单路10Gb/s或25Gb/s速率的光模块采用SFP封装将电芯片和TO封装的光收发组件焊接到PCB板上组成光模块。但对于40G及以上速率的高速光模块,受激光器速率限制(多为25G),主要通过多通道并行实现,如40G由4×10G实现,而100G则由4×25G实现。蝶形封装:壳体通常为长方体,结构及实现功能通常比较复杂,可以内置制冷器、热沉、陶瓷基块、芯片、热敏电阻、背光监控,并且可以支持所有以上部件的键合引线。BOX封装属于蝶形封装的一种,用于多通道并行封装。

WaytoICT- Explore ICT Technology, Build Your Tech Path 3807

More Effective C#——详析GetHashCode方法

GetHashCode函数一般是在操作HashTable或者Dictionary之类的数据集的时候被调用,目的是产生一个Key,为了方便在 HashTable或者 Dictionary中的检索。 每个类型,不管是值类型还是引用类型,都提供这个基本函数,同样也可以像重写ToString或者Equals函数一样去重写它。但是不建议重写此函数,而且在使用这个函数也需要加倍小心。...

aj 1090

【Q1/论文复现】:利用 CHARLS 数据库考察抗高血压药物依从性和认知衰退

摘要: 北京大学团队基于CHARLS数据(2011-2018)的纵向研究发现,抗高血压药物高依从性能显著延缓中国45岁及以上社区中老年人的认知衰退。研究表明,坚持服药者7年内全局认知衰退速度降低0.014SD/年,记忆功能衰退减缓0.023SD/年,效果接近正常血压人群水平。研究还提示社会经济地位(SES)可能通过影响用药依从性间接调控认知衰老进程。该成果为高血压管理对认知保护提供了人群级证据,发表于《BMC Medicine》(DOI:10.1186/s12916-025-03949-8)。

dingdianbangni的博客 809

C#GetHashCode()方法的使用

GetHashCode()方法 问题描述 往往我们会看到Equals()与GetHashCode()方法体一起使用,但对于为什么要使用却是迷迷糊糊,很多时候都是套用别人的,现在我就具体写写我的一些看法,如有写得不好的地方,请给予指正! 例如: public class DComparer : IEqualityComparer<double> { public bool Equals(double b1, double b2) { return (Math.Abs(b1 - b2) <

weixin_44899642的博客 6377

临床预测模型R语言全流程实战:从建模到Bootstrap验证的完整代码

临床预测模型是利用患者特征预测疾病结局发生概率的重要统计工具,其核心在于通过Logistic回归或Cox比例风险模型建立风险函数,并借助ROC曲线、校准曲线等指标评估模型的区分度与校准度。Bootstrap内部验证和DCA决策曲线分析则是当前审稿人关注的焦点,前者用于校正过拟合带来的乐观估计,后者用以判断模型在临床决策中的实际净获益。在肿瘤预后、慢病风险评估等场景中,基于R语言的模型构建与列线图可视化已成为论文发表的关键环节。本文以survival包自带肺癌数据为例,系统展示从数据预处理、变量筛选到多因素建

weixin_33483304的博客 243

家用扫地机器人实物拆解报告-从顶盖到每一颗螺丝 · 逐层拆解旗舰扫拖一体机器人

2026年旗舰扫拖机器人拆解报告:采用D形机身设计,主机重4.5kg,基站重12kg。核心配置包括RK3588S+STM32H743双处理器、8颗21700电池、LDS激光雷达和双摄像头+结构光导航系统。创新设计亮点:锥形滚刷自动排毛发、活水循环拖地系统、基站集成450W强力集尘和自动上下水模块(带三重防漏保护)。整机采用模块化设计,关键部件均支持快速更换,在密封性、防呆设计和降本增效方面展现出成熟的工程智慧。

智能硬件研发,欢迎交流 517

c#的Equals

c#的 Equals有很多方式。 [b]1 静态 object.Equals[/b] [code="c#"] public static bool Equals(object objA, object objB) { return objA == objB || (objA != null && objB != null && objA.Equals(objB)); }[/c...

1206

华为OD机试双机位C卷-停车场收入统计 (Py/Java/C/C++/Js/Go)

华为OD机试双机位C卷 停车场收入统计,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 停车场收入统计。

qq_45776114的博客 2185

c#identity Server 4 身份认证

c#identity Server 4 身份认证。

qq_43510923的博客 547

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

对HashCode的理解

文章目录Hash什么是hash常见Hash函数直接取余法乘数去整法平方取中法HashCodeObject.hashCode()Objects.hashCode(),Arrays.hashCode()String.hashCode()Interger.hashCode()hashCode的作用equals和hashCode为什么是31 Hash 什么是hash hash,翻译散列或哈希,就是把任意长...

N_a_n的博客 925

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

HashEncode哈希加密

HashEncode哈希加密帮助类库源码下载: [C#] 纯文本查看 复制代码 ? 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

xiaobaibai1216的专栏 911

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java面试--HashCode

面试题:hashCode知道是干什么的吗?如果要你重写,需要注意哪些点?(腾讯面试题) 一、hashCode简介 public int hashCode():hashCode是根类Obeject中的方法。默认情况下,Object中的hashCode() 返回对象的32位jvm内存地址。也就是说如果对象不重写该方法,则返回相应对象的32为JVM内存地址。 二、hashCode注意点 ...

小刺猬 4677

C# 中的“相等判断”

C# 中的“相等判断” C# 中判断相等的方式很多,例如: 双等号 ==​ 实例的 Equals()​ 方法 ​Object.Equals()​ 静态方法 ​Object.ReferenceEquals()​ 方法 ​EqualityComparer\u0026lt;int\u0026gt;.Default.Equals()​ 方

fenfenfen520a的博客 790

必须掌握的hashcode()方法

点击上方“后端技术精选”,选择“置顶公众号”技术文章第一时间送达!作者:续杯凉茶cnblogs.com/whgk/p/6071617.html推荐阅读(点击可跳转)1....

Java笔记虾 7万+

c# - Asp.net Core Identity - 操作步骤

1. Define a new class, derived from IdentityUser public class AppUser : IdentityUser { public string DisplayName { get; set; } } 2. In your DataContext, change 'public class DataCo...

yuxuac的专栏 1561

C#的Equals方法

先给上微软的实例链接,Object.Equals方法, 然后是我的总结 总起:Equals比较取决于参数是  值类型 和 引用类型 1.引用类型 1.1  Equals 等于ReferenceEquals(System.Object,System.Object) 1.2 Reference equality 就是比较引用指向是否相同 1.3 指向同一个对象,就是返

lmf757300481的博客 3090

C#的GetHashCode的用法

建议了解一下哈希和哈希表,就会知道这个哈希码(HashCode)是什么东西了。 简而言之,哈希代码是一个用于在相等测试过程中标识对象的数值。它还可以作为一个集合中的对象的索引。如果两个对象的 Equals 比较结果相等,则每个对象的 GetHashCode 方法都必须返回同一个值。 如果两个对象的比较结果不相等,这两个对象的 GetHashCode 方法不一定返回不同的值。 简而言之,如果你发现两个对象 GetHashCode() 的返回值相等,那么这两个对象就很可能是同一个对象;但如果返回值不相等,这两个

qq_18072961的博客 2230

C# == 与 equals

C#中我们常常要用到这两个方式去做等于判断,那么接下来就一起看一下两者的区别吧。值类型: 结果:在C#中对于值类型的比较不管是用【==】还是【equals】都是对于其内容的比较,也就是说对于其值的比较,相等则返回true 不相等则返回false;引用类型: string 类型: 但是对于除string类型以外的引用类型 【==】比较的是在对象在栈上的引用是否相同而【equals】则比较的是对象在堆上的内容是否相同 结果:而当我定义两个object 引用指向两个string变量时再进行比较 结

have a nice day 3945

C#中的ReferenceEquals、Equals以及==

C#中有一共有四种相等性判断方法: //Object中定义的三个方法 public static bool ReferenceEquals(object objLeft, object objRight); public static bool Equals(object objLeft, object objRight); public virtual bool Equals...

weixin_30421525的博客 514

c语言equals用法,C# 中 equals( ) 和 == 的区别和用法

Equals:下面的语句中,x、y 和 z 表示不为 null 的对象引用。* 除涉及浮点型的情况外,x.Equals(x) 都返回 true。* x.Equals(y) 返回与 y.Equals(x) 相同的值。* 如果 x 和 y 都为 NaN,则 x.Equals(y) 返回 true。* 当且仅当 x.Equals(z) 返回 true 时,(x.Equals(y) && ...

weixin_42139302的博客 3532

C# == 与 Equals

/结果为false //使用ReferenceEquals比较两对象的引用是否相等。

Liumotor的博客 2763
上一篇: 设计模式介绍:依赖注入代码示例
下一篇: Java程序员从Spring框架中学习到的三种最佳实践
codinghello
博客等级 码龄25年 47粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值