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. Yet Another Array Queries Problem CodeForces - 863D (暴力/思维)

    You are given an array a of size n, and q queries to it. There are queries of two types: 1 li ri — p ...

  2. 学习Java第三周

    这是学习java的第三周 上周想要学习的这周也完成了,研究和测试代码花费了大约2个小时,发现这些内容方法居多,想要熟练掌握就要好好记忆了 包装类 数字处理类 Object类 Java类包 内部类 下一 ...

  3. Python网络编程笔记二

    使用select模块实现IO多路复用服务端 import socket import select #windows上只支持select.select,不支持poll epoll HOST = &qu ...

  4. Django 中配置MySQL数据库

    在Django的项目中会默认使用sqlite的数据库 配置MySQL需要在setting.py 里加入以下设置: 配置数据库 DATABASES = { 'default': { 'ENGINE': ...

  5. vue动态组件-根据数据展示特定组件

    vue中有个内置组件component,利用它可以实现动态组件,在某些业务场景下可以替换路由 假设有以下三个组件: com1.com2.com3 有一个外层路/coms中代码如下 <templa ...

  6. 0006 列表(ul、ol、dl)

    1. 列表标签(重点) 学习目标 理解 无序列表的应用场景 自定义列表的应用场景 应用 无序列表语法 自定义列表语法 问? 前面我们知道表格一般用于数据展示的,但是网页中还是有很多跟表格类似的布局,如 ...

  7. 给你的 ASP.NET Core 程序插上 Feature Flag 的翅膀

    前言 我们知道,目前大多数应用程序在正式发布到生产环境之前都会经历多个不同的测试环境,通过让应用程序在多个不同的环境中运行来及时发现并解决问题,避免在线上发生不必要的损失.这是对于整个软件的发布流程来 ...

  8. win32汇编简单实现窗口程序

    .386 .model flat,stdcall option casemap:none ;========================== ;include部分 include windows. ...

  9. 小小知识点(二十七)20大5G关键技术

    5G网络技术主要分为三类:核心网.回传和前传网络.无线接入网. 核心网 核心网关键技术主要包括:网络功能虚拟化(NFV).软件定义网络(SDN).网络切片和多接入边缘计算(MEC). 1 网络功能虚拟 ...

  10. 使用JavaMail发送邮件(含文本/附件/图片)的工具类

    记录利用公司内搭建的smtp邮件服务器,使用javax mail发送邮件的程序 package com.test.mailTest; import java.util.Date; import jav ...