于快速创建 IEqualityComparer<T> 实例的类 Equality<T>
于快速创建 IEqualityComparer<T> 实例的类 Equality<T>
原文中的 Equality<T> 实现如下:
1 |
public static class Equality<T> |
代码中的问题使用红色粗体标出。
在改进之前,我们需要先弄清两个关于 null 值的两个问题:
关于 null 的两个问题
将定有一个 Person 类:
1 |
public class Peron |
问题一,两个 null 值是否相等?
1 |
Peron p1 = new Peron { Name = null };
|
请告诉我 b1 和 b2 的值。
问题二,为 null 时 HashCode 应该是什么?
1 |
var h1 = StringComparer.InvariantCulture.GetHashCode(p1.Name); |
请告诉我 h1 和 h2 的值。
建议大家想下这两个问题,答案就不给出了,自行调试吧。
你的答案和调试得出的结果可能会有出入,如果这样你得好好思考下了。
Equality<T> 改进后的代码
改进后,代码如下:
1 |
public static class Equality<T> |
以上代码黄色高亮部分为新加入代码。
用法:
1 |
var personNameComparer = Equality<Peron>.CreateComparer(p => p.Name); |
第 28 行代码
此行代码会有很大争议,它会影响 p7 与 p8 比较的结果 b4。
也许有的朋友认为应该将这行代码修改为:
1 |
if(x== null) |
这样得出 b4 的值为 true.
我不赞同这种方式,我的观点是:“p=>p.Name”指定使用 Person 的 Name 进行相等比较,Person若不存在(值为 null), Name 更不存在,也谈不上相等,所以应返回 false。
当然还有另一种想法,Person 不存在,没法比,应该抛出异常。
第 33 行代码
也可以写成:
1 |
return RuntimeHelpers.GetHashCode(null); |
RuntimeHelpers 类在 System.Runtime.CompilerServices 命名空间下,我在反编译 Object 时,在 GetHashCode() 方法中发现了它。
复杂情况下的使用
一位园友问我这样一个问题,如下两个类:
1 |
public class Employee |
要创建 Employee 的相等比较器,根据其学校(School)的所在城市(City)。不考虑一个 Employee 多个 School 的情况,但要考虑 Employee 的 School 属性为 null 的情况(可能没上过学)。
用以下方式创建:
1 |
var employeeComparer = Equality<Employee>.CreateComparer(i => i.School.City); |
运行时,可能会出错。执行比较时,遇到 Employee 的 School 属性为 null ,便会抛出 NullReferenceException。
一种可行的写法是:
1 |
var companylComparer = Equality<School>.CreateComparer(i => i.City); |
是的,分两步。也许是麻烦了些,不过试想下如果没有 Equality<T> 类的帮助,如果实现这个这个相等比较器?相当麻烦,不信可以试着写下。
简单测试下:
1 |
var v0 = new Employee { School = new School { City = "Beijing" } };
|
再搞复杂一点
把前面的 City 变成一个类,代码如下:
1 |
public class Employee |
还是要求创建 Employee 的相等比较器,根据 Employee 的 School 的 City 的 Country 来判断。要考虑各引用属性的为 null 时的情形。
还不过瘾,就再加点难度! Country 比较时不考虑大小写。
嘻嘻,有谁能告诉我如何创建,可以使用本文中的 Equality<T>,也可以不用。当然,越简洁越好。
知道的话,请回复我,非常期待你的参与!
于快速创建 IEqualityComparer<T> 实例的类 Equality<T>的更多相关文章
- 快速创建 IEqualityComparer 实例:改进
两年前,我写了篇文章<快速创建 IEqualityComparer<T> 和 IComparer<T> 的实例>,文中给出了一个用于快速创建 IEqualityCo ...
- 一分钟在云端快速创建MySQL数据库实例
本教程将帮助您了解如何使用Azure管理门户迅速创建,连接,配置MySQL 数据库 on Azure.完成本教程后,您将在Azure上拥有一个示例MySQL数据库服务器,并了解如何使用管理门户执行基本 ...
- 工厂模式,根据ID创建对应的实例类
工厂模式,根据ID创建对应的实例类 // // main.cpp // TestCPP1 // // Created by bianchx on 15/4/27. // Copyright (c) 2 ...
- 快速创建SpringBoot2.x应用之工具类自动创建web应用、SpringBoot2.x的依赖默认Maven版本
快速创建SpringBoot2.x应用之工具类自动创建web应用简介:使用构建工具自动生成项目基本架构 1.工具自动创建:http://start.spring.io/ 2.访问地址:http://l ...
- 应用DriverManager类创建sqlserver数据库连接实例 JSP中使用数据库
JSP中使用数据库 1.JDBC介绍 java数据库连接(java Database Connectivity ,JDBC)是一种用于执行SQL语句的JavaAPI ,由一组使用java编程语言编写的 ...
- vs里根据json快速创建对应类的方法
有时候,我们在调用别人接口的时候,服务端返回了一个json格式的字符串,我们要获取json里面的数据的话一般有两种方式: 1.通过正则 2.反序列化成一个对象 第一种方式这里不再多说,主要说一下第二种 ...
- Foundation框架 - 快速创建跨平台的网站页面原型
API参考:http://foundation.zurb.com/docs/ 作为网页设计和开发人员,我们面临着以下几个严峻的问题: 每天,人们用来上网的设备种类和数量都在不断上升. 为每种设备设计开 ...
- 快速创建显示数字数据的动画——CountUp.js
由于项目需求,需要写一个数字增/减量的动画特效,最后找到了CountUp.js CountUp.js是一个无依赖,轻量级的JavaScript“类”,可用于快速创建以更有趣的方式显示数字数据的动画. ...
- 十分钟快速创建 Spring Cloud 项目
一般来说,Intelij IDEA 可以通过 Maven Archetype 来快速生成Maven项目,其实 IDEA 集成了 Spring 官方提供的 Spring Initializr,可以非常方 ...
随机推荐
- 控制执行流程——(Java学习笔记三)
if-else 控制程序流程最基本的形式 格式: if(boolean - expresion){ statement } 或 if(boolean - expresion){ stateme ...
- win7或windows server 2008 R2 被远程登录日志记录 系统日志
事件查看器 → Windows 日志 → 安全 (win7 事件查看器 打开方式 :计算机 右键 → 管理 → 计算机管理 → 系统工具 → 事件查看器 windows server 2008 ...
- suggest的使用方法
suggest的使用方法注意: 1. 要表示汉语的"建议做某事",英语通经常使用suggest doing sth,而不能用 suggest to do sth: 2. " ...
- C++ Primer 学习笔记_54_类和数据抽象 --拷贝构造函数、赋值运算符
拷贝控制 --复制构造函数.赋值操作符 引言: 当定义一个新类型时,须要显式或隐式地指定复制.赋值和撤销该类型的对象时会发生什么– 复制构造函数.赋值操作符和析构函数的作用! 复制构造函数: ...
- mac github工具将命令当下来的代码拖入macgithub中就可以
mac github工具将命令当下来的代码拖入macgithub中就可以,刚開始傻傻的就知道点击那个加入button,总是在当下来的文件夹下创建个文件夹.并且代码不能同步
- JAVA于Get和Post差异请求
1. get 离server在对数据的访问.post 它是对server数据的传输. get 请求返回 request - URI 随机信息指出,. Post 请求发送电子邮件.观看新闻或交互式用户发 ...
- CQRS(命令查询职责分离)和 EDA(事件驱动架构)
转载CQRS(命令查询职责分离)和 EDA(事件驱动架构) 上一篇:<IDDD 实现领域驱动设计-SOA.REST 和六边形架构> 阅读目录: CQRS-命令查询职责分离 EDA-事件驱动 ...
- Java8的日期和时间的库20经常使用的演示样本
除了lambda表达,stream以及从一些小的改进,Java 8还推出了新的日期和时间API,在本教程中,我们将展示通过几个简单的任务来学习如何使用示例Java 8这组API.Java至今.日历和时 ...
- MVC 验证码
验证码类 public class VerifyCode { public string checkCode = String.Empty; public byte[] BuildImg() { in ...
- Entity Framework查询原理
Entity Framework查询原理 前言 Entity Framework的全称是ADO.NET Entity Framework,是微软开发的基于ADO.NET的ORM(Object/Rela ...