C# Equals 和 GetHashCode 方法认知及Distinct方法解析
参照:
生成 C# Equals 和 GetHashCode 方法重写 - Visual Studio (Windows) | Microsoft Learn
如何修改字符串内容 - C# | Microsoft Learn
在C#中,Equals 和 GetHashCode 方法用于对象的比较和哈希值计算。它们在值类型和值类型的行为上有所不同。
值类型(Value Types)
Equals方法:- 默认实现: 对于值类型,
Equals方法默认比较对象的值,而不是它们的引用。比如,对于结构体(struct)类型,Equals方法会比较两个结构体的每个字段的值是否相等。 - 可以覆盖: 值类型可以覆盖
Equals方法以实现自定义的比较逻辑。
- 默认实现: 对于值类型,
GetHashCode方法:- 默认实现: 值类型的
GetHashCode方法默认基于对象的字段值生成哈希码。这通常会用到GetHashCode方法的字段值,并确保相同值的对象具有相同的哈希码。 - 建议覆盖: 自定义值类型时,建议覆盖
GetHashCode方法,以确保哈希码在逻辑上与Equals方法一致。特别是如果值类型用于哈希集合(如HashSet<T>)或字典(如Dictionary<TKey, TValue>)中,正确的GetHashCode实现非常重要。
- 默认实现: 值类型的
引用类型(Reference Types)
Equals方法:- 默认实现: 对于引用类型,
Equals方法默认比较对象的引用是否相同,也就是比较对象的内存地址。如果需要比较对象的内容,需要覆盖Equals方法。 - 可以覆盖: 引用类型通常会覆盖
Equals方法以实现基于内容的比较逻辑,而不是基于引用。
- 默认实现: 对于引用类型,
GetHashCode方法:- 默认实现: 引用类型的
GetHashCode方法默认基于对象的引用生成哈希码。这通常是内存地址的哈希值。 - 建议覆盖: 当覆盖
Equals方法时,也应当相应地覆盖GetHashCode方法,以保证相等的对象具有相同的哈希码。这对使用哈希集合或字典中的对象尤为重要
- 默认实现: 引用类型的
重写Equals 和 GetHashCode 实现
目的:有时候我们需要比较的是两个对象各属性值是否相等而不是比较内存地址是否也一样。这时候我们需要对Equals 和 GetHashCode 进行重写
重写前
using System.Linq;
List<Student> list = new List<Student>(){
new Student(1,new Card(1,"小明")),new Student(2,new Card(1,"小明")),new Student(3,new Card(3,"小华")),new Student(4,new Card(2,"小李"))
};
var list2 = list.Select(s=>s.MyCard).Distinct().ToList();
Console.WriteLine();
public class Card
{
public string Str { get; set; }
public int Number { get; set; }
public Card(int num,string strs){
Str = strs;
Number = num;
} }
public class Student
{
public int No { get; set; }
public Card MyCard { get; set; }
public Student(int num, Card card)
{
MyCard = card;
No = num;
}
}
list2:出现两个小明

重写后
using System.Linq;
List<Student> list = new List<Student>(){
new Student(1,new Card(1,"小明")),new Student(2,new Card(1,"小明")),new Student(3,new Card(3,"小华")),new Student(4,new Card(2,"小李"))
};
var list2 = list.Select(s=>s.MyCard).Distinct().ToList();
Console.WriteLine();
public class Card
{
public string Str { get; set; }
public int Number { get; set; }
public Card(int num,string strs){
Str = strs;
Number = num;
}
public override int GetHashCode()
{
return Number.GetHashCode();
}
public override bool Equals(object obj)
{
return Equals(obj as Card);
}
public bool Equals(Card card)
{
return card != null &&
Number == card.Number; }
}
public class Student
{
public int No { get; set; }
public Card MyCard { get; set; }
public Student(int num, Card card)
{
MyCard = card;
No = num;
}
}
list2结果:

结论:对于引用类的集合,distinct是没办法去重的。因为distinct调用的是默认的Equals的方法,比较的是引用地址。引用地址不一样,即使各个属性一样,也是不会相等。
破解引用类型集合distinct不生效的方式有两种,第一种如上重写默认的Equals的方法,第二种是定义一个新的属性比较的Compare的方法,作为Distinct的参数
list = list.Distinct((a, b) => a.Age == b.Age && a.Name == b.Name).ToList();
性能比较:C# Linq 的三种去重方式(Distinct)_linq distinct-CSDN博客
因为我们重写了Card的
string 是一个特殊的引用类型。它被设计为不可变的(immutable),这意味着一旦创建了 string 对象,其内容不能被更改,如果有新的。
参照:字符串 - C# 编程指南 | Microsoft Learn
string 类型的 Equals 和 GetHashCode 实现
Equals方法:- 实现:
string类型的Equals方法被重写(override)以比较两个字符串的内容,而不是它们的引用。具体来说,它会检查两个字符串的字符序列是否相同。 - 逻辑: 方法会比较两个字符串的长度和每个字符。如果长度相同且每个字符都相等,则
Equals方法返回true,否则返回false。
public override bool Equals(object obj)
{
if (obj is string otherString)
{
return StringComparer.Ordinal.Equals(this, otherString);
}
return false;
}- 实现:
GetHashCode方法:- 实现:
string类型的GetHashCode方法基于字符串的内容生成哈希码。它会使用字符串中的字符序列来计算哈希值,以确保相同内容的字符串具有相同的哈希码。 - 逻辑: 通常,
GetHashCode使用字符串中的字符和其位置来计算哈希值。C# 中,string的哈希算法依赖于字符内容和排序。由于字符串是不可变的,这样的实现保证了相同的字符串内容总是会生成相同的哈希码。
public override int GetHashCode()
{
// 使用字符序列生成哈希码的实现
}- 实现:
C# Equals 和 GetHashCode 方法认知及Distinct方法解析的更多相关文章
- 重写类的Equals以及重写Linq下的Distinct方法
当自定义一个类的时候,如果需要用到对比的功能,可以自己重写Equals方法,最整洁的方法是重写GetHashCode()方法. 但是,这个方法只适用于对象自身的对比(如if(a==b))以及字典下的C ...
- 如何很好的使用Linq的Distinct方法
Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1" Person3: Id=2, Name=&quo ...
- Linq的Distinct方法的扩展
原文地址:如何很好的使用Linq的Distinct方法 Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1&qu ...
- 扩展Linq的Distinct方法动态根据条件进行筛选
声明为了方便自己查看所以引用 原文地址:http://www.cnblogs.com/A_ming/archive/2013/05/24/3097062.html Person1: Id=1, Nam ...
- Equals()和GetHashCode()方法深入了解
最近在看Jeffrey Richter的CLR Via C#,在看到GetHashCode()方法的时候,有一个地方不是特别明白,就是重写Equals()方法时为什么要把GetHashCode()方法 ...
- ( 转 ) 聊一聊C#的Equals()和GetHashCode()方法
聊一聊C#的Equals()和GetHashCode()方法 博客创建一年多,还是第一次写博文,有什么不对的地方还请多多指教. 关于这次写的内容可以说是老生长谈,百度一搜一大堆.大神可自行绕路. ...
- 聊一聊C#的Equals()和GetHashCode()方法
博客创建一年多,还是第一次写博文,有什么不对的地方还请多多指教. 关于这次写的内容可以说是老生长谈,百度一搜一大堆.大神可自行绕路. 最近在看Jeffrey Richter的CLR Via C#,在看 ...
- 我看C#的Equals()和GetHashCode()方法
首先先谈一下Equals()这个方法: Equals()方法,来自于Object,是我们经常需要重写的方法.此方法的默认实现大概是这样的: public virtual bool Equals(obj ...
- 【转载】聊一聊C#的Equals()和GetHashCode()方法
首先先谈一下Equals()这个方法: Equals()方法,来自于Object,是我们经常需要重写的方法.此方法的默认实现大概是这样的: public virtual bool Equals(obj ...
- C# Distinct方法的使用笔记
引自:http://blog.csdn.net/shaopengfei/article/details/36426763 从C# 3.0开始提供了Distinct方法,这对于集合的使用有了更为丰富的方 ...
随机推荐
- [记录点滴]编译安装luarocks、luacheck、luautf8
[记录点滴]编译安装luarocks.luacheck.luautf8 0x00 摘要 记录一次安装luarocks&第三方库的过程. 0x01 luarocks 如今每个语言体系中都有一个包 ...
- 2024年! kali高级配置加一键教程加前人的经验加后人的实践
2024年! kali高级配置加一键教程加前人的经验加后人的实践 记录一下配置kali的过程,方便下次需要直接复制粘贴 直接终端按照顺序输入就可以配置好 作者已踩点,请放心 kali更换国内源 sud ...
- [ABC297F] Minimum Bounding Box 2 题解
容斥真有趣. 有一个性质: 两个相同的子矩阵,对答案的贡献一定相同. 所以就只需要枚举矩阵大小即可. 我们设当前矩阵长 \(i\) 宽 \(j\)(对应的,\(H\) 为长,\(W\) 为宽),假如要 ...
- 松下机器人示教器AUR01062触摸无反维修
Panasonic松下机器人示教器AUR01062触摸无反应解决方案 松下机器人示教器现象:触摸屏幕时鼠标箭头无任何动作,没有发生位置改变. 原因:造成此现象产生的原因很多,下面就松下机器人维修中示教 ...
- Linux MiniMal版本常规所需环境安装
Docker 环境安装 前置工作 之 基础环境安装 当前环境 centos7.9 64位 minimal版本 当前环境为 root用户 若当前存在Docker环境 需卸载 yum remove doc ...
- DataX - [03] 使用案例
题记部分 001 || mysql2hdfs (1)查看MySQL被迁移的数据情况 (2)根据需求确定reader为mysqlreader,writer为hdfswriter 查看reader和wri ...
- 2024.11.19随笔&联考总结
联考 看到 T1 就知道一定是简单计数题然后发现 \(O(n)\) 可以过于是就大概写了写式子就开写.写的过程中犯了一些低级错误,代码重构了一次才过.耽误的时间比较久.然后开 T2,一眼有一个 \(O ...
- Supac 如何修改地址界限高层点
编辑->图层->运算 2.选择z ->填写高度 如-180阶段 3.保存
- class com.ttsx.activity.item.dao.entity.RoleMenu ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method. 报错解决办法
启动项目的时候,有几条WARN警告,如图: 引起原因: 是因为数据表实体类 没有di导致的. 例如: 解决办法: 增加实体id字段!或可以忽略!不影响程序!
- SpringSecurity5(1-快速入门)
依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri ...