C# 父类实现的 IEquatable<T> 接口,重写的相等性判断函数都能被子类继承

news2024/12/23 20:44:15

实验代码

Son s1 = new(), s2 = new();

Console.WriteLine("_ = s1 == s2");
_ = s1 == s2;
Console.WriteLine();

Console.WriteLine("_ = s1 != s2;");
_ = s1 != s2;
Console.WriteLine();

Console.WriteLine("_ = s1.Equals(s2);");
_ = s1.Equals(s2);
Console.WriteLine();

Console.WriteLine("_ = ((object)s1).Equals(s2);");
_ = ((object)s1).Equals(s2);
Console.WriteLine();

Console.WriteLine("s1 is IEquatable<Father>");
Console.WriteLine(s1 is IEquatable<Father>);
Console.WriteLine();

Console.WriteLine("s1.GetHashCode()");
Console.WriteLine(s1.GetHashCode());
Console.WriteLine();

public class Father : IEquatable<Father>
{
	public virtual int A { get; set; }
	public virtual int B { get; set; }

	public override bool Equals(object? obj)
	{
		Console.WriteLine("object Equals");
		if (obj is not null and Father)
		{
			Father f = (Father)obj;
			return f.A == A && f.B == B;
		}

		return false;
	}

	public override int GetHashCode()
	{
		Console.WriteLine("GetHashCode");
		return 0;
	}

	public static bool operator ==(Father left, Father right)
	{
		Console.WriteLine("比较==");
		return left.Equals(right);
	}

	public static bool operator !=(Father left, Father right)
	{
		Console.WriteLine("比较!=");
		return !(left == right);
	}

	public bool Equals(Father? other)
	{
		Console.WriteLine("IEquatable Equals");
		return ((object)this).Equals(other);
	}
}

public class Son : Father
{
	public override int A { get => base.A; set => base.A = value; }
}

运行结果

_ = s1 == s2
比较==
IEquatable Equals
object Equals

_ = s1 != s2;
比较!=
比较==
IEquatable Equals
object Equals

_ = s1.Equals(s2);
IEquatable Equals
object Equals

_ = ((object)s1).Equals(s2);
object Equals

s1 is IEquatable<Father>
True

s1.GetHashCode()
GetHashCode
0

在父类重写的 Equals 方法,继承的 IEquatable 接口,重写的 == ,!= 运算符,重写的 GetHashCode 方法在子类中仍然是表现为被重写的状态。

子类实现 IEquatable 接口

现在让子类也实现 IEquatable 接口

Son s1 = new(), s2 = new();

s1.Equals(s2);

public class Father : IEquatable<Father>
{
	public virtual int A { get; set; }
	public virtual int B { get; set; }

	public override bool Equals(object? obj)
	{
		Console.WriteLine("object Equals");
		if (obj is not null and Father)
		{
			Father f = (Father)obj;
			return f.A == A && f.B == B;
		}

		return false;
	}

	public override int GetHashCode()
	{
		Console.WriteLine("GetHashCode");
		return 0;
	}

	public static bool operator ==(Father left, Father right)
	{
		Console.WriteLine("比较==");
		return left.Equals(right);
	}

	public static bool operator !=(Father left, Father right)
	{
		Console.WriteLine("比较!=");
		return !(left == right);
	}

	public bool Equals(Father? other)
	{
		Console.WriteLine("IEquatable Equals");
		return ((object)this).Equals(other);
	}
}

public class Son : Father, IEquatable<Son>
{
	public bool Equals(Son? other)
	{
		Console.WriteLine("IEquatable<Son>.Equals");
		return ((object)this).Equals(other);
	}
}

运行结果

IEquatable<Son>.Equals
object Equals

Equals 方法的重载

此时代码提示如下
在这里插入图片描述
子类实现接口后,调用的默认就是子类实现的 Equals 方法。也可以用强制转换调用父类的 Equals 方法
在这里插入图片描述
这里属于 Equals 方法的不同类型的重载。通过 public override bool Equals(object? obj) 重写的 Equals 方法也是一种重载。这个重载是每一个 object 的子类都有的,不重写这个方法时比较的是两个对象的引用是否相等。

所有判断相等性的运算符、方法必须一起重写

上面那些判断相等性的方法、运算符必须要么一起重写,要么全部不重写。实现了 IEquatable 接口后也要重写全部。如果不全部重写,这些不同的相等性判断方法返回结果不一致会造成混乱。

对象放到哈希表的过程

对象在放到哈希表里首先是计算哈希值,然后尝试放到哈希表中的对应位置。如果该位置已经有一个对象了,再调用 Equals 方法判断是不是同一个对象,如果是,就不再放一次了。如果不是,则说明发生了哈希冲突,此时会将新对象用链表挂在哈希表该位置。

重写 Equals 方法后,如果将对象放在哈希表里,必须重写 GetHashCode 方法

重写相等性判断方法时,如果想让对象能够在哈希表里正常工作,必须也重写 GetHashCode 方法。GetHashCode 方法原本是根据引用值生成哈希码,原本的相等性运算也是根据引用值。这种情况可以正常工作。但是,如果重写了 Equals 方法,不重写 GetHashCode 方法,会导致明明相等的两个对象返回的哈希值不同(因为他们的引用不同),于是哈希表中的两个位置储存了两个相等的对象。

重写 GetHashCode 的注意事项

  1. 不要使用会变化的字段生成哈希码。因为字段变化后,生成的哈希码不同,此时再调用 GetHashCode 方法得到的哈希码不同,这会导致字段变化后无法在哈希表中找到该对象了。
  2. 两个对象使用 Equals 方法判断相等性返回 true 时,GetHashCode 方法必须能够返回相同的值。否则会导致两个相等的对象具有不同的哈希值,这会导致哈希表中有重复的元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/784441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为数通HCIP-BGP基础

AS&#xff08;自治系统/路由域&#xff09; 定义&#xff1a;运行相同路由协议&#xff0c;具有相同管理规则的区域&#xff08;一般为一个企业网&#xff09;&#xff1b; 按照传递路由时是否携带掩码分类&#xff1a; 1、有类路由协议 路由传递时&#xff0c;无需携带掩…

linux下的tomcat

springboot项目端口是8080&#xff0c;部署到linux运行之后&#xff0c;为什么能检测到tomcat 手动安装tomcat&#xff0c;以下是在 Linux 系统上安装 Tomcat 的步骤&#xff1a; 下载 Tomcat 安装包。您可以从 Tomcat 官方网站&#xff08;https://tomcat.apache.org/ ↗&…

Bagging方法6大面试热点问题

Q1&#xff1a;为什么Bagging算法的效果比单个评估器更好&#xff1f; 该问题其实是在考察Bagging方法降低模型泛化误差的基本原理。 泛化误差是模型在未知数据集上的误差&#xff0c;更低的泛化误差是所有机器学习/深度学习建模的根本目标。在机器学习当中&#xff0c;泛化误差…

python获取图片坐标系中的图形,将其展示到新的坐标系中,并存储到excel中

python获取图片坐标系中的图形&#xff0c;将其展示到新的坐标系中&#xff0c;并存储到excel中 1.原始图片 2.重新定义转换的图片 3.代码展示 import cv2 import numpy as np import matplotlib.pyplot as plt import pandas as pddef get_curve_vertices(lines):vertices…

【文末送书】Python高并发编程:探索异步IO和多线程并发

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。搜…

RISC-V汇编指令

写在最前面&#xff1a;这一篇是UC Berkeley的CS61C的笔记&#xff0c;根据我自己的理解进行学习记录&#xff0c;其中贴的一些图片来自于课程PPT。 了解汇编之前&#xff0c;我们需要先了解为什么需要汇编&#xff1f;以下是我的理解&#xff1a; 机器执行的命令都是些二进制…

六边形架构和分层架构的区别?

六边形架构和分层架构是什么&#xff1f; 六边形架构&#xff08;Hexagonal Architecture&#xff09;和分层架构&#xff08;Layered Architecture&#xff09;是两种常见的软件架构模式。六边形架构强调将核心业务逻辑与外部依赖解耦&#xff0c;通过接口与外部世界进行通信。…

hcip mgre与rip实验

要求&#xff1a; 1.toop搭建 2.IP地址规划 R1g 0/0/1 192.168.1.1 24 s 4/0/0 188.0.0.2 24 t&#xff1a;10.0.0.1 24R2 s 4/0/0 188.0.0.1 24 s 4/0/1 188.0.1.1 24 s 3/0/0 188.0.2.1 24 loop0 8.8.8.8 24 t&#xff1a;10.0.0.2 24 R3g…

本地 IDC 中的 K8s 集群如何以 Serverless 方式使用云上计算资源

作者&#xff1a;庄宇 在前一篇文章《应对突发流量&#xff0c;如何快速为自建 K8s 添加云上弹性能力》中&#xff0c;我们介绍了如何为 IDC 中 K8s 集群添加云上节点&#xff0c;应对业务流量的增长&#xff0c;通过多级弹性调度&#xff0c;灵活使用云上资源&#xff0c;并通…

Python自动化测试框架pytest的详解安装与运行

这篇文章主要为大家介绍了Python自动化测试框架pytest的简介以及安装与运行&#xff0c;有需要的朋友可以借鉴参考下希望能够有所帮助&#xff0c;祝大家多多进步 1. pytest的介绍 pytest是一个非常成熟的全功能的python测试工具&#xff0c;它主要有以下特征&#xff1a; 简…

二进制子集题解

样例输入&#xff1a; 13样例输入&#xff1a; 0 1 4 5 8 9 12 13思路分析&#xff1a; 这道题大体就是进制转换然后按位 d f s dfs dfs。进制转换比较好理解&#xff0c;不懂得可以自行 b d f s ( 百度优先搜索 ) bdfs(百度优先搜索) bdfs(百度优先搜索)一下。 代码&#…

【LeetCode】260.只出现一次的数字 III(找出单身狗)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负。 目录 前言&#xff1a; 一只单身狗&#xff1a; 两只单身狗&#xff1a; 前言&#x…

HTTPS安全套接字层超文本传输协议

HTTPS安全套接字层超文本传输协议 HTTPS简介HTTPS和HTTP的主要区别客户端在使用HTTPS方式与Web服务器通信时的步骤SSL/TLS协议的加密&#xff08;握手&#xff09;过程为什么数据传输阶段使用对称加密HTTPS 的优点HTTPS 的缺点HTTPS 的优化证书优化会话复用 HTTPS简介 HTTP协议…

Keil系列教程07_Configuration(一)

1写在前面 本文带来的内容为“Configuration”&#xff0c;即配置。而这里的“配置”和前面“工程目标选项配置”是完全不同的两种配置。 工程目标选项配置是针对工程目标&#xff0c;保存在工程文件&#xff08;.uvprojx和.uvoptx&#xff09;。这里的Configuration是针对IDE…

在本地git仓库查看远端的URL

右键调出选项栏 选择git-远端&#xff0c;选择远端的内容就可以看到URL了

数据结构之时间复杂度

目录 一、时间复杂度的概念 二、大O的渐进表示法 三、常见时间复杂度计算举例 一、时间复杂度的概念 时间复杂度的定义&#xff1a;在计算机科学中&#xff0c;算法的时间复杂度是一个函数&#xff0c;它定量描述了该算法的运行时间。一个算法执行所耗费的时间&#xff0c;从…

OpenCV图像处理-图像分割-MeanShift

MeanShift 1. 基本概念2.代码示例 1. 基本概念 MeanShift严格说来并不是用来对图像进行分割的&#xff0c;而是在色彩层面的平滑滤波。它会中和色彩分布相近的颜色&#xff0c;平滑色彩细节&#xff0c;侵蚀掉面积较小的的颜色区域&#xff0c;它以图像上任意一点P为圆心&…

架构重构实践心得

一、前言 大多数的技术研发都对重构有所了解&#xff0c;而每个研发又都有自己的理解。从代码重构到架构重构&#xff0c;我参与了携程大型全链路重构项目&#xff0c;积累了一点经验心得&#xff0c;在此抛砖引玉和大家分享。 二、重构的定义 重构是指在不改变外部行为的情…

MySQL数据库(十)

目录 一、Java的数据库编程&#xff1a;JDBC 1.1JDBC工作原理 二、Java具体连接数据库 2.1准备过程 2.2代码连接数据库 一、Java的数据库编程&#xff1a;JDBC JDBC&#xff0c;即Java Database Connectivity&#xff0c;java数据库连接。是一种用于执行SQL语句的Java API&…

华为认证HCIA-HCIP-HCIEdatacom题库解析+机构视频+实验

题库包含有2023年最新HCIA-datacom题库、HCIP-datacom题库&#xff0c;HCIE-datacom题库&#xff0c; 云计算HCIA&#xff0c;HCIP题库&#xff0c;云服务HCIA&#xff0c;HCIP题库&#xff0c;华为存储HCIP题库&#xff0c;华为安全HCIP题库 &#xff0c;学习笔记&#xff0c;…