参照:

生成 C# Equals 和 GetHashCode 方法重写 - Visual Studio (Windows) | Microsoft Learn

如何修改字符串内容 - C# | Microsoft Learn

在C#中,Equals 和 GetHashCode 方法用于对象的比较和哈希值计算。它们在值类型和值类型的行为上有所不同。

值类型(Value Types)

  1. Equals 方法:

    • 默认实现: 对于值类型,Equals 方法默认比较对象的值,而不是它们的引用。比如,对于结构体(struct)类型,Equals 方法会比较两个结构体的每个字段的值是否相等。
    • 可以覆盖: 值类型可以覆盖 Equals 方法以实现自定义的比较逻辑。
  2. GetHashCode 方法:

    • 默认实现: 值类型的 GetHashCode 方法默认基于对象的字段值生成哈希码。这通常会用到 GetHashCode 方法的字段值,并确保相同值的对象具有相同的哈希码。
    • 建议覆盖: 自定义值类型时,建议覆盖 GetHashCode 方法,以确保哈希码在逻辑上与 Equals 方法一致。特别是如果值类型用于哈希集合(如 HashSet<T>)或字典(如 Dictionary<TKey, TValue>)中,正确的 GetHashCode 实现非常重要。

引用类型(Reference Types)

  1. Equals 方法:

    • 默认实现: 对于引用类型,Equals 方法默认比较对象的引用是否相同,也就是比较对象的内存地址。如果需要比较对象的内容,需要覆盖 Equals 方法。
    • 可以覆盖: 引用类型通常会覆盖 Equals 方法以实现基于内容的比较逻辑,而不是基于引用。
  2. 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 实现

  1. 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;
    }
  2. GetHashCode 方法:

    • 实现: string 类型的 GetHashCode 方法基于字符串的内容生成哈希码。它会使用字符串中的字符序列来计算哈希值,以确保相同内容的字符串具有相同的哈希码。
    • 逻辑: 通常,GetHashCode 使用字符串中的字符和其位置来计算哈希值。C# 中,string 的哈希算法依赖于字符内容和排序。由于字符串是不可变的,这样的实现保证了相同的字符串内容总是会生成相同的哈希码。
    public override int GetHashCode()
    {
    // 使用字符序列生成哈希码的实现
    }

C# Equals 和 GetHashCode 方法认知及Distinct方法解析的更多相关文章

  1. 重写类的Equals以及重写Linq下的Distinct方法

    当自定义一个类的时候,如果需要用到对比的功能,可以自己重写Equals方法,最整洁的方法是重写GetHashCode()方法. 但是,这个方法只适用于对象自身的对比(如if(a==b))以及字典下的C ...

  2. 如何很好的使用Linq的Distinct方法

    Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1" Person3: Id=2, Name=&quo ...

  3. Linq的Distinct方法的扩展

    原文地址:如何很好的使用Linq的Distinct方法 Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1&qu ...

  4. 扩展Linq的Distinct方法动态根据条件进行筛选

    声明为了方便自己查看所以引用 原文地址:http://www.cnblogs.com/A_ming/archive/2013/05/24/3097062.html Person1: Id=1, Nam ...

  5. Equals()和GetHashCode()方法深入了解

    最近在看Jeffrey Richter的CLR Via C#,在看到GetHashCode()方法的时候,有一个地方不是特别明白,就是重写Equals()方法时为什么要把GetHashCode()方法 ...

  6. ( 转 ) 聊一聊C#的Equals()和GetHashCode()方法

    聊一聊C#的Equals()和GetHashCode()方法   博客创建一年多,还是第一次写博文,有什么不对的地方还请多多指教. 关于这次写的内容可以说是老生长谈,百度一搜一大堆.大神可自行绕路. ...

  7. 聊一聊C#的Equals()和GetHashCode()方法

    博客创建一年多,还是第一次写博文,有什么不对的地方还请多多指教. 关于这次写的内容可以说是老生长谈,百度一搜一大堆.大神可自行绕路. 最近在看Jeffrey Richter的CLR Via C#,在看 ...

  8. 我看C#的Equals()和GetHashCode()方法

    首先先谈一下Equals()这个方法: Equals()方法,来自于Object,是我们经常需要重写的方法.此方法的默认实现大概是这样的: public virtual bool Equals(obj ...

  9. 【转载】聊一聊C#的Equals()和GetHashCode()方法

    首先先谈一下Equals()这个方法: Equals()方法,来自于Object,是我们经常需要重写的方法.此方法的默认实现大概是这样的: public virtual bool Equals(obj ...

  10. C# Distinct方法的使用笔记

    引自:http://blog.csdn.net/shaopengfei/article/details/36426763 从C# 3.0开始提供了Distinct方法,这对于集合的使用有了更为丰富的方 ...

随机推荐

  1. JMeter + ant + Jenkins 接口测试持续集成

    JMeter + ant + Jenkins 接口测试持续集成 操作系统:linux 环境变量 地址 jdk11 https://www.oracle.com/java/technologies/do ...

  2. 使用python实现一个可自动部署hexo博客的gitee webhook

    文章首发在我的博客:https://blog.liuzijian.com/post/af1f30e3-c846-650e-9a3f-34e326bf950d.html hexo博客想在提交后自动部署, ...

  3. ESP8266+AT指令,使用MQTT协议连接阿里云

    AT指令集 AT+CWMODE=1 AT+CWJAP="热点名","热点密码" AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com& ...

  4. WPF 事件实现MVVM中的Command绑定

    1. 在ViewModel中弹出消息提示框,需要添加下面的代码块: <dxmvvm:Interaction.Behaviors> <dx:DXMessageBoxService /& ...

  5. 职场软素质&算法工程师的硬素质--卓越的职场人需要的42种能力

    经过自己在实际的工作中摸爬滚打,个人觉得一些方面的能力是非常重要的,可以让自己在职场中快速的脱颖而出,因此,从硬实力,软实力两个方面进行总结如下: 软实力: (1)解决问题的能力 (2)预估风险的能力 ...

  6. Flink学习(十三) Flink 常见核心概念分析

    分布式缓存熟悉 Hadoop 的你应该知道,分布式缓存最初的思想诞生于 Hadoop 框架,Hadoop 会将一些数据或者文件缓存在 HDFS 上,在分布式环境中让所有的计算节点调用同一个配置文件.在 ...

  7. Week09_day05(Hbase的安装搭建)

    搭建完全分布式集群 HBase集群建立在hadoop集群基础之上,所以在搭建HBase集群之前需要把Hadoop集群搭建起来,并且要考虑二者的兼容性.现在就以5台机器为例,搭建一个简单的集群. 软件版 ...

  8. Elasticsearch搜索引擎学习笔记(一)

    核心概念 ES -> 数据库 索引index -> 表 文档 document -> 行(记录) 字段 fields -> 列 安装Elasticsearch 1. 上传后解压 ...

  9. 【MATLAB习题】工程测试时域、频域分析

    代码: classdef App_uoye < matlab.apps.AppBase % Properties that correspond to app components proper ...

  10. 强!10.8K star!推荐一款用于威胁预防、安全检测的开源监控平台,功能非常强大!!

    在当今数字化时代,网络安全威胁日益严峻,企业和组织对于高效.强大的安全解决方案的需求也愈发迫切. 今天给大家分享一个专注于安全监控的开源项目:Wazuh,正是应对这一挑战的有力武器,专门用于帮助个人和 ...