c# 复写Equals方法的实现

作者:桃花换小鱼干儿 时间:2023-06-09 01:35:35 

应用情景:

很多标准的方法都是利用Object.Equals方法来做对比的,例如LIst.Remove

假设 某些情景下我们希望引用类型判断“相等”时不去看地址是不是同一个,而是看某些属性是不是一样就可以了。(例如身份证ID是一个就认为是同一个人)

复写方法如下范例所示:

Main{
   List<People> nList = new List<People> { new People( 1 ), new People( 2 ), new People( 3 ) };
   People onePeople = new People( 1 );
   nList.Remove( onePeople );

}

class People
{
   public People( int nID )
   {
       ID = nID;
   }
   int ID;

public override bool Equals( object obj )
   {
       return Equals( obj as People );
   }

bool Equals( People other )
   {
       return other != null
           && ID == other.ID;
   }

}

P.s. 最好也重新overide GetHashCode方法:
(7跟13只是常用的手法,拿質數來乘,確保hash code是獨一無二),也可以加入 ^ 计算

public override int GetHashCode()
{
   int hash =13;
   hash = (hash * 7) + ID== null ? 0 : ID.GetHashCode();
}

原因是:

1.Equal是判断是否指向同一个地址
2.每个对象都会有一个独一无二的HashCode
一旦override了Equal方法,却不override GetHashCode方法会导致两个判断为相同(利用Equal判断)的对象,Hash值却不同。
承上,在使用到HashCode的地方(例如Dictionary中的key),两个相同对象可能会被重复加入到Dictionary中

什么时候需要重写 Equals() 方法

引用类型:

只有当需要修改该引用类型所定义的语义时,才应该重写实例版本的 Equals() 方法。如果类型需要采用值语义而不是引用语义(或者说,需要按照对象内容而不是对象身份来进行比较),那么就应该针对这个类型重写实例版本的 Object.Equals() 方法。

引用类型一般不需要重写 operator==()。

值类型:

创建值类型的时候,总是应该针对这个类型重写 ValueType.Equals() 方法。
因为值类型都继承自 System.ValueType 类,System.ValueType 类默认通过反射来实现比较,效率不够高。

值类型中默认的 == 运算符会默认通过反射进行比较,因此,也应该重写 == 操作符。

重写 Equals() 方法时的注意事项

Equals() 方法必须满足等同关系的 3 项数学性质:自反性、对称性、可传递性。
Equals() 方法决不应该抛出异常。
重写 Equals() 方法时,只有在基类型的 Equals(object) 不是由 System.Object 或 System.ValueType 所提供的情况下,才需要调用基类型的版本。
重写 Equals() 的时候,还应该让该类型实现 IEquatable<T> 接口。
重写 Equals() 方法后,通常应该同时重写 GetHashCode() 方法。

重写 GetHashCode() 方法时的注意事项

如果 Equals() 方法认定两个对象相等,那么这两个对象的 HashCode 也必须相同;
对任意对象来说,其 HashCode 必须在生命周期内保持不变;
HashCode 计算方法应该将其值均匀地映射到各个整数上,避免堆集。
一种常用的 HashCode 算法是:对类型中的每个相互独立的不可变字段调用 GetHashCode() 方法,并对返回的 HashCode 进行异或(XOR)运算,将得到的最终结果作为对象本身的 HashCode 。

来源:https://blog.csdn.net/qq_41617697/article/details/123716144

标签:c#,复写Equals,c#,重写Equals
0
投稿

猜你喜欢

  • C# String常用函数的使用详解

    2022-04-05 05:29:02
  • java.lang.Runtime.exec() Payload知识点详解

    2023-11-30 09:56:10
  • Java中防止数据重复提交超简单的6种方法

    2022-03-18 11:03:22
  • Java毕业设计实战之在线高中考试系统的实现

    2021-07-04 06:15:20
  • Java遗传算法之冲出迷宫

    2022-01-12 21:34:58
  • Android ContentProvider查看/读取手机联系人实例

    2021-10-13 07:10:13
  • JAVA生成短8位UUID的实例讲解

    2021-08-21 04:26:19
  • 详解C#对路径...的访问被拒绝解决过程

    2021-06-01 11:12:10
  • 如何使用try-with-resource机制关闭连接

    2022-04-25 01:36:54
  • IDEA代码规范插件P3C+代码注释模板配置方法

    2022-10-30 17:32:55
  • 一文带你了解C#中的协变与逆变

    2022-08-06 22:31:21
  • java static块和构造函数的实例详解

    2021-10-04 07:30:17
  • Android应用内悬浮窗的实现方案示例

    2022-05-07 20:29:24
  • springboot跨域如何设置SameSite的实现

    2022-08-03 21:27:07
  • Kotlin扩展方法超详细介绍

    2023-05-31 16:31:23
  • Android RecyclerView使用GridLayoutManager间距设置的方法

    2023-03-20 07:32:44
  • Windows下Flutter+Idea环境搭建及配置

    2022-01-22 18:12:13
  • java原生序列化和Kryo序列化性能实例对比分析

    2023-11-26 16:04:20
  • 详解Java单元测试之JUnit篇

    2023-06-12 16:42:13
  • Mockito mock Kotlin Object类方法报错解决方法

    2022-03-10 15:23:37
  • asp之家 软件编程 m.aspxhome.com