C#中Equals和GetHashCode使用及区别

 更新时间:2020年02月03日 14:27:14   作者:HueiFeng  
这篇文章主要介绍了C#中Equals和GetHashCode使用及区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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

相关文章

  • 使用C#实现数据结构堆的代码

    使用C#实现数据结构堆的代码

    这篇文章主要介绍了使用C#实现数据结构堆,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • C#实现TCP和UDP通信的示例详解

    C#实现TCP和UDP通信的示例详解

    这篇文章主要为大家详细介绍了C#实现TCP和UDP通信的相关知识,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-03-03
  • C#操作Byte数组和十六进制进行互转

    C#操作Byte数组和十六进制进行互转

    这篇文章介绍了C#操作Byte数组和十六进制进行互转的的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C#使用Socket上传并保存图片的方法

    C#使用Socket上传并保存图片的方法

    这篇文章主要介绍了C#使用Socket上传并保存图片的方法,涉及C#使用Socket进行文件传输的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • C#中使用1.7版本驱动操作MongoDB简单例子

    C#中使用1.7版本驱动操作MongoDB简单例子

    这篇文章主要介绍了C#中使用1.7版本驱动操作MongoDB简单例子,本文给出了连接MongoDB、操作MongoDB数据等例子,需要的朋友可以参考下
    2015-01-01
  • c#中SqlHelper封装SqlDataReader的方法

    c#中SqlHelper封装SqlDataReader的方法

    这篇文章主要介绍了c#中SqlHelper封装SqlDataReader的方法,涉及C#针对数据库相关操作封装与使用的技巧,需要的朋友可以参考下
    2015-05-05
  • DevExpress实现TreeList按条件隐藏节点CheckBox的方法

    DevExpress实现TreeList按条件隐藏节点CheckBox的方法

    这篇文章主要介绍了DevExpress实现TreeList按条件隐藏节点CheckBox的方法,需要的朋友可以参考下
    2014-08-08
  • C#使用Ado.Net更新和添加数据到Excel表格的方法

    C#使用Ado.Net更新和添加数据到Excel表格的方法

    这篇文章主要介绍了C#使用Ado.Net更新和添加数据到Excel表格的方法,较为详细的分析了OLEDB的原理与使用技巧,可实现较为方便的操作Excel数据,需要的朋友可以参考下
    2015-04-04
  • WPF使用FontAwesome字体图标

    WPF使用FontAwesome字体图标

    这篇文章介绍了在WPF中使用FontAwesome字体图标的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • C#程序启动项的设置方法

    C#程序启动项的设置方法

    这篇文章主要为大家详细介绍了C#程序启动项的设置方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11

最新评论