C# - 如何让类型可以比较
C# - 如何让类型可以比较
IComparable
.NET 里,IComparable是用来作比较的最常用接口。
如果某个类型的实例需要与该类型的其它实例进行比较或者排序的话,那么该类型就可以通过实现IComparable接口来达到此目的。
IComparable只提供了一个方法:
先看一个例子,这里使用了string,因为string实现了该接口:
其结果是:
string是通过按位字母进行比较的,“a”就小于“b”,所以上述str1应该是小于str2的。
而CompareTo方法返回的是int类型,而比较的结果呢,可能有三种情况:
x == y
x < y
x > y
再通过上面的例子,我们可以看出来:
针对x.CompareTo(y),
如果 x == y,那么 结果 = 0
如果 x < y,那么结果 < 0
如果 x > y,那么结果 > 0
我们可以把代码重构一下,提取出一个低级别方法,便于逻辑复用:
顺便提一下,string并没有实现> < == 等等操作符。
int
所有的原始类型都实现了IComparable。
所以使用上面的方法,也可以比较原始数据类型:
当然这些类型也可以使用操作符,例如:
而string没有实现这些操作符,所以这样写就是错误的:
相等性 vs 比较
直接看图:
其中,针对比较性,System.object并没有支持,因为对于大多数类型而言,对它们的实例进行比较排序是没有意义的。
例如3 < 4,这样就是合理的;而提交按钮 < 取消按钮,这就没有意义了;这个委托 < 另一个委托,这也没有意义。
针对相等性而言,IEquatable仅仅就是对object里的那些Equals方法的补充。而针对比较性而言,IComparable是主打的方式。
其它的方式都有对应。
下面两个黄色的通过”插件的方式“实现的,这里只提一下,不介绍了。
比较性 只比较值
判断相等性的时候,可能判断的是引用相等或者是值相等。
而进行比较排序的时候,其比较的只能是值,因为对引用进行比较排序是没有意义的。
而==和!=操作符可以为原始数据类型和引用类型来使用,而>, <, >=, <= 只能用于原始数据类型。
在自定义类型上实现比较
其实我通常不在我的类型上去实现IComparable,包括引用类型和原始类型。
因为是这样的,比如说有一个Person(人)这个类型,我想对它排序,按照年龄排序,可以;按照姓名排序,也可以;按照身高排序,也可以;但是没有任何一种排序对人来说是最理所当然的。
更好的办法是实现某种比较器。
但是有时候还是需要实现IComparable,那么下面就讲一下怎么做。
值类型
Person Struct:
如果直接使用我们之前的方法,则会报错:
因为它没实现IComparable接口。
使用大于号小于号的话,也会报错:
因为这个类型也没有实现比较操作符。
实现IComparable接口
很简单,直接调用了字段Height的CompareTo方法,因为int类型实现了IComparable接口。
实现比较操作符
一共四个操作符:<, >, <=, >=,必须都得实现。
代码是:
这个很简单就不解释了。
现在代码不会报错了:
其运行结果是:
运行OK了,看似没问题,然后,还有一个问题:
使用等号判断相等性的代码会报错。
如果你不是用==操作符的话,那么代码是没问题的,也是可以进行比较的,也没人强制要求实现==和!=操作符。但是这很奇怪!因为你说 p1 > p2,这个成立,然后再说 p1 != p2这个就编译错误,那就不合理了。
所以,如果你实现了比较操作符,那么相等性操作符也应该一同实现了:
那么既然==和!=都实现了,那么其它的相等性判断方法也应该一同实现:
object.Equals()
object.GetHashCode()
IEquatable
看起来挺麻烦,但这只是一个struct,还是相对简单的。。。。
但针对struct,其实还没完,还有一个非泛型的IComparable接口,泛型出现之前,一直都是用这个接口的。
这个接口现在来说没什么用了,但是如果有其它遗留的老代码需要使用你这个struct,你可能还需要把这个接口实现一下。。。
引用类型
引用类型除了需要考虑上面struct考虑的那些东西外,还需要考虑更多的东西。
首先,需要在CompareTo里面检查是否为null,和类型检查。
而如果Person是一个没有seal的class,那问题就更大了,以前文章里提到的OOP继承问题、类型安全问题、相等性问题将全部出现。因为类型安全和比较性还是没法一起很愉快的工作。反正会很混乱。。。
所以如果事seal的class,那么在其上实现比较性的话还勉强可以接受;否则的话,祝好运。。。
泛型
之前在相等性的文章里,提到过,针对泛型代码来说,==和!=操作符不能很好的工作,而object.Equals()却可以。
这点在比较性里面也是一样的。针对泛型的比较,你需要使用IComparable.CompareTo()方法,而不是比较的操作符>, <, >=, <=等(即使实现了比较操作符)。
如果我把之前的方法代码改成使用比较操作符:
那么就会报错,因为无法约束泛型实现了某些操作符。。。但可以考虑在接口里面实现比较操作符。。。
但是实现比较性的话:
实现IComparable接口
也可选去实现比较操作符。
原文地址https://www.cnblogs.com/cgzl/p/10777541.html

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python实现微信消息防撤回
Python实现微信消息防撤回微信(WeChat)是腾讯公司于2011年1月21日推出的一款社交软件,8年时间微信做到日活10亿,日消息量450亿。在此期间微信也推出了不少的功能如:“摇一摇”、“漂流瓶”、“朋友圈”、“附近的人”、“公众平台”、“小程序”等等,涵盖了我们生活的方方面面,微信正在慢慢践行着他们的口号:微信,是一个生活方式 一、背景介绍产品的更新迭代必然会伴随着功能的推出和下线,今天我们要讲的便是微信在2014年推出的一个小小的新功能:撤回消息,使用此功能者提神醒脑、神清气爽,但被施用者却可能会抓耳挠腮、咬牙切齿的想知道你到底撤回了啥,这就是所谓的好奇害死猫(Curiosity kills the cat),今天我们就来用Python实现防微信消息撤回,满足一下大家的好奇心!在这里插入图片描述 二、功能设计我们希望当有好友或者群中有人撤回消息的时候,第一时间能把原消息、发送者信息转发到文件助手中(当然你也可以把消息发回给他,哈哈),这样方便我们查看。 给大家来演示一下实现的功能。在这里插入图片描述 三、功能实现1.微信撤回消息实现原理我们先来了解一下微信撤回消息的原理: ...
- 下一篇
Python基础面试,看这篇文章画重点吧,Python面试题No1
Python基础面试,看这篇文章画重点吧,Python面试题No1为什么有这个系列的文章一直想写一些更加基础的文章,但是总是想不到好的点子,最近到了就业季,一大堆学生面临就业了,正好,从Python的面试题出发,分析和解答一些常见的面试题,并且总结一些文字。 每一讲涉及5~10道面试题,整个系列的文章初步规划有20篇。 今天的面试题第1题:1行代码实现1到100的和?分析:这题考察的是对Python内置函数的了解程度 Python常见的内置函数有python内置函数官方查询手册如下https://docs.python.org/3/library/functions.html 图片中我框选的是比较常用的一些,你可能见过,这题考察的是sum也就是求和具体的使用 sum(iterable[, start]) iterable -- 可迭代对象,如:列表、元组、集合。start -- 指定相加的参数,如果没有设置这个值,默认为0。例如 sum([1,2,3]) # 结果为6sum([1,2,3],5) # 结果为11python一行代码如何实现1~100的和 还要用到第二个内置函数 rang...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Mario游戏-低调大师作品
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Linux系统CentOS6、CentOS7手动修改IP地址