C#中Equals和GetHashCode使用及区别
作者:HueiFeng 发布时间:2023-12-10 14:47:27
Equals和GetHashCode
Equals每个实现都必须遵循以下约定:
自反性(Reflexive): x.equals(x)必须返回true.
对称性(Symmetric): x.equals(y)为true时,y.equals(x)也为true.
传递性(Transitive): 对于任何非null的应用值x,y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)必须返回true.
一致性(Consistence): 如果多次将对象与另一个对象比较,结果始终相同.只要未修改x和y的应用对象,x.equals(y)连续调用x.equals(y)返回相同的值l.
非null(Non-null): 如果x不是null,y为null,则x.equals(y)必须为false
GetHashCode:
两个相等对象根据equals方法比较时相等,那么这两个对象中任意一个对象的hashcode方法都必须产生同样的整数。
在我们未对对象进行修改时,多次调用hashcode使用返回同一个整数.在同一个应用程序中多次执行,每次执行返回的整数可以不一致.
如果两个对象根据equals方法比较不相等时,那么调用这两个对象中任意一个对象的hashcode方法,不一同的整数。但不同的对象,产生不同整数,有可能提高散列表的性能.
IEqualityComparer实现
下面我们创建一个学生类,从而进一步的实现我们对象数据的对比
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
通过如下代码我们将通过distinct方法实现我们的过滤.
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>
{
new Student{ Name = "MR.A", Age = 32},
new Student{ Name = "MR.B", Age = 34},
new Student{ Name = "MR.A", Age = 32}
};
Console.WriteLine("distinctStudents has Count = {0}", students.Distinct().Count());//distinctStudents has Count = 3
Console.ReadLine();
}
}
我们需要达到的是忽略相同数据的对象,但是并没有达到我们如期的效果.因为是distinct默认比较的是对象的引用...所以这样达不到我们预期效果.那我们修改一下来实现我们预期效果.
在默认情况下Equals具有以下行为:
如果实例是引用类型,则只有引用相同时, Equals才会返回true。
如果实例是值类型,则仅当类型和值相同时, Equals才会返回true。
Distinct(IEnumerable, IEqualityComparer)
通过使用指定的 IEqualityComparer 对值进行比较,返回序列中的非重复元素.
类型参数
TSource source 的元素类型。
参数
source IEnumerable 要从中移除重复元素的序列。
comparer IEqualityComparer 用于比较值的 IEqualityComparer。
返回
IEnumerable
一个包含源序列中的非重复元素的 IEnumerable。
我们来看如下代码片段
public class StudentComparator : EqualityComparer<Student>
{
public override bool Equals(Student x,Student y)
{
return x.Name == y.Name && x.Age == y.Age;
}
public override int GetHashCode(Student obj)
{
return obj.Name.GetHashCode() * obj.Age;
}
}
上述代码片段如果两个Equals返回的true并且GetHashCode返回相同的哈希码,则认为两个对象相等.
重写Equals和GetHashCode
var stu1 = new Student { Name = "MR.A", Age = 32 };
var stu2 = new Student { Name = "MR.A", Age = 32 };
bool result = stu1.Equals(stu2); //false because it's reference Equals
上述代码片段执行后结果非预期效果.我们将进一步的去实现代码,以达到预期效果....
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public override bool Equals(object obj)
{
var stu = obj as Student;
if (stu == null) return false;
return Name == stu.Name && Age == stu.Age;
}
public override int GetHashCode()
{
return Name.GetHashCode() * Age;
}
}
var stu1 = new Student { Name = "MR.A", Age = 32 };
var stu2 = new Student { Name = "MR.A", Age = 32 };
bool result = stu1.Equals(stu2); //result is true
我们再使用LINQ Distinct方法进行过滤和查询,同时将会检查Equals和GetHashCode
List<Student> students = new List<Student>
{
new Student{ Name = "MR.A", Age = 32},
new Student{ Name = "MR.B", Age = 34},
new Student{ Name = "MR.A", Age = 32}
};
Console.WriteLine("distinctStudents has Count = {0}", students.Distinct().Count()); //distinctStudents has Count = 2
作者:@冯辉
出处:https://www.cnblogs.com/yyfh/p/12245916.html?utm_source=tuicool&utm_medium=referral
来源:https://www.cnblogs.com/yyfh/p/12245916.html


猜你喜欢
- Java RandomAccessFile 指定位置实现文件读取与写入RandomAccessFile是属于随机读取类,是可以对文件本身的内
- 实例如下:public class DataTypeChangeHelper { /** * 将一个单字节的b
- /// <summary> /// 转义字符
- 引言在项目中,时间的使用必不可少,而java 8之前的时间api Date和Calander等在使用上存在着很多问题,于是,jdk1.8引进
- 看下效果图主要看下自定义view 代码public class ProcessImageView extends ImageView{ &
- 本文实例为大家分享了java实现猜字母游戏的具体代码,供大家参考,具体内容如下案例需求:StepOne:系统随机生成一组随机的字符数组(不重
- 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时
- 如论实施敏捷的团队,或者实施 DevOps 的团队,通过自动化测试提高测试效率和软件质量都是其共同的选择。UI 自动化测试是自动化化测试当中
- mybatis项目CRUD步骤1.pom.xml引入相应的依赖<?xml version="1.0" encodi
- ListView的多种样式条目展示这里给大家介绍一下简单的ListView的多种样式展示在布局文件中和往常一样写一个ListViwe的布局
- BigDecimal除法精度和格式化输出import java.math.BigDecimal;import java.math.MathC
- 1、首先创建一个按钮<Buttonandroid:id="@+id/click"android:layout_wi
- 前言: 最近一直在看Launcher模块,经过差不多两个月学习,终于摸透了Launcher的一些主要功能实现,目前继续还处于摸索状态。未看L
- 环境: idea2020.1插件: LeetCode-editor 6.7一、IDEA安装LeetCode插件安装完成重启idea打开插件U
- 微信平台开放后倒是挺火的,许多第三方应用都想试下,毕竟可以利用微信建立起来的关系链来拓展自己的应用还是挺不错的,可以节约很多在社交方面的开销
- 前言: 有时候我们需要实现长按选择文字功能,比如阅读器一般都有这个功能,有时候某个自定义控件上可能就有这种需求,如何实现呢?正好最近还算闲,
- 目录1. 应用场景1.1. 保障线程安全1.2. 显示传递参数2. 实现原理3. 注意事项ThreadLocal是线程私有的局部变量存储容器
- 本文实例为大家分享了Android实现百度地图两点画弧线的具体代码,供大家参考,具体内容如下import android.support.a
- Java中的StringUtils引入及使用pom.xml中引入依赖<!-- https://mvnrepository.com/ar
- Java调用接口获取json数据保存到数据库今天给大家带来一个调用接口,来获取数据解析后再保存到数据库中的业务,业务中的Mapper和实体类