C# 中的IComparable和IComparer
前言
在开发过程中经常会遇到比较排序的问题,比如说对集合数组的排序等情况,基本类型都提供了默认的比较算法,如string提供了按字母进行排序,而int整数则是根据整数大小进行排序.但是在引用类型中(具有多个字段),那么这个排序当然也是取决于我们特定的值。
IComparable接口
该接口由其值可以排序或排序的类型实现,并提供强类型的比较方法以对泛型集合对象的成员进行排序,例如数字可以大于第二个数字,一个字符串可以在另一个字符串之前以字母顺序出现。他要求实现类型定义的一个方法,CompareTo(T)该方法指示当前实现在排序顺序中的位置是在同一个类型和第二个对象之前、之后还是与其相同。通常,不会直接从开发人员代码中调用方法。相反他由List.Sort()和Add等方法自动调用。
通常,提供Icomparable实现的类型还IEquatable实现接口。IEquatable接口Equals定义方法,该方法确定实现类型的实例的相等性。
CompareTo(T)方法的实现必须Int32返回具有以下三个值之一的,如下表所示。
值 | 含义 |
---|---|
小于零 | 此对象在排序顺序中位于CompareTo方法所指定的对象之前。 |
零 | 此当前实例在排序顺序中与CompareTo方法参数指定的对象出现在同一位置。 |
大于零 | 此当前实例位于排序顺序中由CompareTo方法自变量指定的对象之后。 |
示例:
class Student : IComparable { public string Name { get; set; } public int Age { get; set; } public int CompareTo(object obj) { if (!(obj is Student)) { throw new ArgumentException("Compared Object is not of student"); } Student student = obj as Student; return Age.CompareTo(student.Age); } }
Ps:我们根据通过Age(int)来进行我们的排序
执行测试
class Program { static void Main(string[] args) { ArrayList studentList = new ArrayList { new Student{Name="a",Age=9 }, new Student{Name="a3",Age=7 }, new Student{Name="a1",Age=6 }, new Student{Name="a2",Age=10 }, }; studentList.Sort(); StudentComparable(studentList); Console.ReadLine(); } private static void StudentComparable(ArrayList studentList) { foreach (Student item in studentList) { Console.WriteLine("Name:{0},Age:{1}", item.Name, item.Age); } } }
输出如下
IComparer接口
IComparable 接口的CompareTo方法一次只能对一个字段进行排序,因此无法对不同的属性进行排序。IComparer接口提供了Compare方法,该方法比较两个对象并返回一个值,该值指示一个对象小于,等于或大于另一个对象。实现IComparer接口的类必须提供比较两个对象的Compare方法。例如,您可以创建一个StudentComparer类,该类实现IComparer,并具有一个Compare方法,该方法按Name比较Student对象。然后,您可以将StudentComparer对象传递给Array.Sort方法,它可以使用该对象对Student对象的数组进行排序。
示例
class StudentComparer : IComparer { public int Compare(object x, object y) { Student x1 = x as Student; Student y1 = y as Student; return x1.Name.CompareTo(y1.Name); } }
Ps:我们根据Name(string)进行排序
执行测试
class Program { static void Main(string[] args) { ArrayList studentList = new ArrayList { new Student{Name="a",Age=9 }, new Student{Name="a3",Age=7 }, new Student{Name="a1",Age=6 }, new Student{Name="a2",Age=10 }, }; studentList.Sort(new StudentComparer()); StudentComparable(studentList); Console.ReadLine(); } private static void StudentComparable(ArrayList studentList) { foreach (Student item in studentList) { Console.WriteLine("Name:{0},Age:{1}", item.Name, item.Age); } } }
输出结果如下
IComparable和IComparer
上述示例中我们将对象进行了多次的装箱和拆箱,那么此时我们可以将方法改为泛型的,泛型的出现也让我们避免了装箱和拆箱的资源浪费.
最终我们实现的代码片段如下:
IComparable
class Student : IComparable<Student> { public string Name { get; set; } public int Age { get; set; } public int CompareTo([AllowNull] Student other) { return Age.CompareTo(other.Age); } }
IComparer
class StudentComparer : IComparer<Student> { public int Compare([AllowNull] Student x, [AllowNull] Student y) { return x.Name.CompareTo(y.Name); } }
总结
参考:https://docs.microsoft.com/en-us/dotnet/api/system.icomparable-1?view=netframework-4.8
示例:https://github.com/hueifeng/BlogSample/tree/master/src/CompareDemo
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
【Java】 如何优雅的做字符串的拼接
在 Java 中,我们都是如何的去做到一个字符串的拼接呢?字符串拼接是我们在Java代码中比较经常要做的事情,就是把多个字符串拼接到一起。都知道,String 是 Java 中一个不可变的类,所以一旦被实例化就无法被修改。那么我们怎么去优雅的拼接我们的字符串呢?老夫这里找了一堆的技术资料,基本上Java中的字符串的拼接都在这了。上面有提到,字符串是不可变的,那么字符串的拼接又是怎么去拼接呢?其实这里讲的字符串的拼接就是将两个字符串拼成新的字符串,也就是最后一共三个字符串。 用 + 来拼接,多简单的事呀 这个应该算是最简单的一种方式了,但是很遗憾得玩告诉你,阿里巴巴在他们的规范里面之处不建议在 for 循环里面使用 “+” 进行字符串的拼接。这里的不建议,其实就是不允许的意思,只是人家说的比较委婉而已。事实上,现在还在拿 “+” 来做拼接的应该是比较少了吧。 我在逛阿里开发者社区的时候看到一篇文章《为什么阿里巴巴不建议在for循环中使用”+”进行字符串拼接》,里面提到这个 拼接符号 “+” 不是一个运算符重载,Java也并不支持这个所谓的运算符重载。作者提出这是 Java 的一个语法糖。...
- 下一篇
C# Lazy Loading
前言 按需加载对象延迟加载实际是推迟进行创建对象,直到对其调用后才进行创建初始化,延迟(懒加载)的好处是提高系统性能,避免不必要的计算以及不必要的资源浪费。 常规有这些情况: 对象创建成本高且程序可能不会使用它。 例如,假定内存中有具有 Orders 属性的 Customer 对象,该对象包含大量 Order 对象,初始化这些对象需要数据库连接。 如果用户永远不要求显示 Orders 或在计算中使用该数据,则无需使用系统内存或计算周期来创建它。 通过使用 Lazy 来声明 Orders对象用于迟缓初始化,可以避免在不使用该对象时浪费系统资源。 对象创建成本高,且希望将其创建推迟到其他高成本操作完成后。 例如,假定程序在启动时加载多个对象实例,但是只需立即加载其中一部分。 可以通过推迟初始化不需要的对象,直到创建所需对象,提升程序的启动性能。(来源官方) 示例 创建用户类 public class User { public string Name { get; set; } public int Age { get; set; } public User() { this.Name =...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8安装Docker,最新的服务器搭配容器使用
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装