于快速创建 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,可以非常方 ...
随机推荐
- Fireasy
Fireasy与Asp.net MVC结合 Fireasy之前都是使用HttpService来为jquery ajax提供服务,这个HttpService实际上和MVC的原理机制是一样的,只是它支 ...
- EF中的贪婪加载和延迟加载(懒加载)
在上一章中,我们使用了Linq对Entity Framework进行了一个查询,但是通过学习我们却发现了懒加载给我来的性能上的开销是很到的,尤其是在循环中,如果数据量不是很多的情况下还可以接受,如果数 ...
- 2013级C++第13周(春)项目——继承的进一步话题与GUI应用开发
课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 第一部分 程序阅读:阅读以下类的定义,请说出在 ...
- 数据库 基于索引的SQL语句优化之降龙十八掌(转)
一篇挺不错的关于SQL语句优化的文章,因不知原始出处,故未作引用说明! 1 前言 客服业务受到SQL语句的影响非常大,在规模比较大的局点,往往因为一个小的SQL语句不够优化,导致数据库性能急 ...
- C#中使用ref 和 out 的一点认识
ref 通常我们向方法中传递的是值,方法获得的是这些值的一个拷贝,然后使用这些拷贝,当方法运行完毕后,这些拷贝将被丢弃,而原来的值不会受到影响. 这种情况是通常的,当然还有另外一种情况,我们向方法传递 ...
- C--运算符,表达式和语句实例
//第五章 运算符,表达式和语句 #include<stdio.h> //引入头文件 #include<math.h> #define ADJUST 7.64 //定义常量 # ...
- Socket 学习(三).2 udp 穿透 服务端 与 客户端 通讯
之前演示的 是 局域网通讯,也可以用作服务器之间的通讯,不能穿透. 想要穿透就要用 udp 了, 后续再讲解 udp 打洞 . 客户端: using System; using System.Wind ...
- asp.net webform生命周期
- 使用ButterKnife无法inject view的解决办法
使用ButterKnife做android开发时,发现无法inject,如下,tvInfo总是null. @InjectView(R.id.textView1Info) TextView tvInfo ...
- Android开发----------- 手电筒改进版本号
在之前的基础上 在 res 目录以下: 加入一个 drawable/local_me.xml localme_cml <selector xmlns:android="http://s ...