C# LINQ之IEqualityComparer<>接口应用
在C#语言中,对集合的条件查询、分组统计等操作使用LINQ非常方便,LINQ的语法格式与SQL非常相似和便捷,而LINQ扩展方法配合Lambda更为简洁,如All、Any、Count、Max等Enumerable类扩展方法,其中Distinct、Intersect、Contains等大量方法中使用了IEqualityComparer<>接口,以实现对象的比较,先看一个查询两个集合交集的代码示例:
public class Product
{
public string Name { get; set; }
public int Code { get; set; }
}
// 产品类的自定义比较器
class ProductComparer : IEqualityComparer<Product>
{
// 实现接口`Equals`方法
public bool Equals(Product x, Product y)
{
// 比较两个对象的内存地址是否一致
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.Code == y.Code && x.Name == y.Name;
}
// 实现接口`GetHashCode`方法
public int GetHashCode(Product product)
{
if (Object.ReferenceEquals(product, null)) return 0;
int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode();
int hashProductCode = product.Code.GetHashCode();
return hashProductName ^ hashProductCode;
}
}
static void Main(string[] args)
{
// 初始化集合数据
Product[] store1 = { new Product { Name = "apple", Code = 9 },
new Product { Name = "orange", Code = 4 } };
Product[] store2 = { new Product { Name = "apple", Code = 9 },
new Product { Name = "lemon", Code = 12 } };
// 查询store1与store2的交集
IEnumerable<Product> duplicates = store1.Intersect(store2, new ProductComparer());
foreach (var product in duplicates)
Console.WriteLine(product.Name + " " + product.Code);
}
/*
代码输出结果: apple 9
*/
看了以上代码后,有的小伙伴会问了,为什么要实现IEqualityComparer<>接口?实现IEqualityComparer<>接口需要注意什么?我来为大家解惑
1. 为什么要实现IEqualityComparer<>接口
是为了复杂类型(类)对象的比较,虽然store1[0]与store2[0]的属性值都一样,但它们是两个不同的对象,如果GetHashCode方法代码如下,则结果为空。
public int GetHashCode(Product product)
{
return product.GetHashCode();
}
2. 如何实现IEqualityComparer<>接口
首先,我们需要了解IEqualityComparer<>接口的两个方法的作用和逻辑,.NET处理时先比较两个对象GetHashCode方法返回的哈希值是否相等,如果不相等则直接返回,不再执行Equals方法,如果哈希值相等则执行Equals方法继续比较!为什么要用两个方法去对比呢?原因是GetHashCode方法比Equals方法效率更高,所以先执行GetHashCode方法。依据上述分析,把示例中GetHashCode方法改为如下代码,则结果是相同的。
public int GetHashCode(Product product)
{
return 0;
}
C# LINQ之IEqualityComparer<>接口应用的更多相关文章
- c# 利用IEqualityComparer接口去除DataTable重复数据
IEqualityComparer主要适用于定义方法以支持对象的相等比较.可以实现集合的自定义相等比较.即,您可以创建自己的相等定义,并指定此定义与接受 IEqualityComparer 接口的集合 ...
- Linq去重 不用实现IEqualityComparer接口的方法超级简单
RskFactorRelation.Instance.GetCache<RskFactorRelation>(true).Where(x => !string.IsNullOrEmp ...
- Linq之IQueryable接口与IEnumberable区别
IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IEnumerable 包含 ...
- 用泛型的IEqualityComparer<T>接口去重复项
提供者:porschev 题目:下列数据放在一个List中,当ID和Name都相同时,去掉重复数据 ID Name 1 张三 1 李三 1 小伟 1 李三 2 李四 2 李武 ----- ...
- linq distinct 不够用了!
问题引出:在实际中遇到一个问题,要进行集合去重,集合内存储的是引用类型,需要根据id进行去重.这个时候linq 的distinct 就不够用了,对于引用类型,它直接比较地址.测试数据如下: class ...
- 《LINQ技术详解C#》-4.LINQ到对象
public static string[] Presidents { get; } = { "Adams", "Arthur", "Buchanan ...
- linq操作符:限定操作符
限定操作符运算返回一个Boolean值,该值指示序列中是否有一些元素满足条件或者是否所有元素都满足条件. 一.All操作符 All方法用来确定是否序列中的所有元素都满足条件.看下面的例子: using ...
- Linq之Distinct详解
前天在做批量数据导入新增时,要对数据进行有效性判断,其中还要去除重复,如果没出现linq的话可能会新声明一个临时对象集合,然后遍历原始数据判断把符合条件的数据添加到临时集合中,这在有了linq之后显得 ...
- IEqualityComparer的使用
当我们用Linq操作我们自定义的对像数组时,我们会发现有些方法直接使用的话根本不起作用,比如:Distinct.Except.Intersect等扩展方法. 对于我们自定义的对象的比较,我们必须实现I ...
- LINQ 方法
过滤操作符 Where 运算符(Linq扩展方法)根据给定条件过滤集合. 在其中扩展方法有以下两个重载.一个过载需要Func <TSource,bool>输入参数和第二个重载方法需要Fun ...
随机推荐
- IceRPC之多路复用传输>快乐的RPC
作者引言 很高兴啊,我们来到了IceRPC之多路复用传输>快乐的RPC,基础引导,打好基础,才能让自已不在迷茫,快乐的畅游世界. icerpc 和多路复用传输 了解 icerpc 协议和多路复用 ...
- Deepin15.11+WIN10 双系统安装过程与遇到的问题(一)
一.deepin安装流程 1.下载 下载深度系统最新版本官网https://www.deepin.org/zh/download/下载深度系统专用U盘启动盘制作工具https://www.deepin ...
- 【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Linux/Linux Container)
在前一篇文章中,我们是把.NET 8应用读取SSL证书(X509)示例部署在App Service Windows环境中,那么如果部署在Linux环境,以及Linux Container中呢? 根据前 ...
- C++笔记(9) 异常
程序有时会遇到运行阶段错误,导致程序无法正常走下去.对于这种问题,处理方法主要有: 1.调用abort() Abort()函数原型位于头文件cstdlib,其典型实现是向标准错误流(即cerr使用的错 ...
- SQL必知必会(第5版) 读书笔记
适用范围 本书涵盖的DBMS一般来说,本书中所讲授的SQL可以应用到任何数据库管理系统(DBMS).但是,各种SQL实现不尽相同,本书介绍的SQL主要适用于以下系统(需要时会给出特殊说明和注释): ❑ ...
- 视图结构 wxml 列表渲染 for
WXML是框架设计的一套标签语言,结合基础组件.事件系统,可以构建出页面的结构. wxml是一个严格的标记性语言,有开始就必须有结束,单标签就一个有结束符 5.1.数据绑定 在js逻辑层中定义数据源, ...
- react 网络请求 axios
react中通过npm来安装axios扩展 cnpm i -S axios 发起请求 import React, { Component } from 'react' import axios fro ...
- SpringBoot系列(五) 接口校验(非空、非法字符/特殊字符、长度等)
1.引入pom依赖 <dependency> <groupId>javax.validation</groupId> <artifactId>valid ...
- JS获取表单所有内容
var formData = {}; var t = $('#Form').serializeArray(); $.each(t, function() { formData[this.name] = ...
- .net程序反编译教程(附反编译工具)
一.以windows服务和winform项目为例,此处用的是winform,发布后的程序都会生成.exe文件,如果有其它关联的程序集,会打包成.dll的动态库文件,一般打包后exe和dll都会带.pd ...