欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#中Equals和GetHashCode使用及区别

程序员文章站 2023-11-18 17:55:16
equals和gethashcodeequals每个实现都必须遵循以下约定: 自反性(reflexive): x.equals(x)必须返回true. 对称性(symmetric): x.equa...

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