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

C#中Equals和GetHashCode的更多相关文章

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

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

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

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

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

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

  4. Java中equals与==和comparaTo的区别

    一.先说说Java中equals和==的区别: Java中的数据类型,可分为两类: 1.基本数据类型(也叫原始数据类型) 八大基本数据类型 char byte short int long doubl ...

  5. java中equals和==的区别 (转)

    java中equals和==的区别  值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...

  6. 【转】Java中equals和==的区别

    [转]Java中equals和==的区别 java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boole ...

  7. C#中 Equals和= =的区别

    C#中 Equals和= =的区别 前言:最近感觉技术进步实在是太慢,一直被游戏缠身不能自拔哈哈,但是游戏打多了真的是感觉整个人浮躁的不行,所以我现在要去游戏多写代码多看书,今天在博客园中看到一个前辈 ...

  8. (转)Java中equals和==的区别

    java中的数据类型,可分为两类:  1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean    他们之间的比较,应用双等号( ...

  9. Java:验证在类继承过程中equals()、 hashcode()、toString()方法的使用

    以下通过实际例子对类创建过程汇中常用的equals().hashcode().toString()方法进行展示,三个方法的创建过程具有通用性,在项目中可直接改写. //通过超类Employee和其子类 ...

随机推荐

  1. FPM简介(定制rpm包)

    FPM简介 fpm是生成rpm包的工具.rpm包的制作,采用fpm工具完成,FPM非常易用,此命令可以把rpm包的安装.卸载做得更加优雅,在安装前可以做一些准备工作,安装后可以做一些收尾工作,在卸载前 ...

  2. 登录密码忘记修改jenkins

    find / -type f -name 'config.xml' 然后需要删除config.xml文件中的以下内容: <useSecurity>true</useSecurity& ...

  3. ssh保持连接不断开

    使用ssh连接服务器,长时间不使用,会自动断开,控制台会卡死无法使用,现提供以下两个方案解决这个问题: [服务器主动保持连接] 修改服务器配置文件: vim /etc/ssh/sshd_config ...

  4. status100到500http响应对应状态解释

    1xx-信息提示 这些状态代码表示临时的响应.客户端在收到常规响应之前,应准备接收一个或多个1xx响应. 100-继续. 101-切换协议. 2xx-成功 这类状态代码表明服务器成功地接受了客户端请求 ...

  5. Python基础复习函数篇

    目录 1.猴子补丁2. global和nonlocal关键字3.迭代器和生成器4.递归函数5.高阶函数和lamdba函数6.闭包7.装饰器 1.   猴子补丁 猴子补丁主要用于在不修改已有代码情况下修 ...

  6. 27.openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽

    openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽 from openpyxl import Workbook,load_workbook from openpyxl.dra ...

  7. window bat批处理 实用脚本

    一行一行读取txt里的内容 @echo off for /f %%i in (C:\Users\86132\Desktop\name.txt) do ( echo %%i>>name2.t ...

  8. Oracle表空间概述及其基本管理

    最近在工作中遇到有同事对Oracle表空间的理解有问题,所以写了这篇文章.我会从概念,管理及特别需要关注的点等几个维度对表空间进行一些介绍.本文以介绍表空间为主,涉及到的其他概念不展开描述.有问题的地 ...

  9. MVC 统一验证Token demo

    /// <summary> /// 获取token /// </summary> /// <param name="staffId"></ ...

  10. 【转】你应该关注的几个Eclipse超酷插件

    本文由 ImportNew - 唐尤华 翻译自 Anton Arhipov.如需转载本文,请先参见文章末尾处的转载要求. 来自非营利性Eclipse基金会的Eclipse IDE以其插件生态系统著称. ...