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
C# 中的IComparable和IComparer的更多相关文章
- C#中的IComparable 和 IComparer 接口,实现列表中的对象比较和排序
借豆瓣某博主的话先对这两个接口进行一个解释: IComparable在要比较的对象的类中实现,可以比较该对象和另一个对象 IComparer在一个单独的类中实现,可以比较任意两个对象. 如果已经支持 ...
- 比较和排序(IComparable和IComparer以及它们的泛型实现)
本文摘要: 1:比较和排序的概念: 2:IComparable和IComparer: 3:IComparable和IComparer的泛型实现IComparable<T>和ICompare ...
- 数组自定义排序:IComparable和IComparer接口
首先先说一下IComparable和IComparer的区别,前者必须在实体类中实现,后者可以单独出现在一个排序类中,即此类只包含一个compare方法. Array类使用快速算法对数组中的元素进行排 ...
- C# 常用接口学习 IComparable 和 IComparer
C# 常用接口学习 IComparable 和 IComparer 作者:乌龙哈里 时间:2015-11-01 平台:Window7 64bit,Visual Studio Community 201 ...
- [0] 关于IComparable和IComparer接口和Comparer类
关于IComparable和IComparer接口 和 Comparer类 IComparable和ICompareframeworkr接口是.net 中比较对象的标准方式,这两个接口之间的区别如下: ...
- C# 比较和排序(IComparable和IComparer以及它们的泛型实现)
准备工作: 1.创建实体类:ClassInfo,默认想要对其按照班级学生数量进行排序 public class ClassInfo { /// <summary> /// 班级名称 // ...
- 比较和排序(IComparable和IComparer以及它们的泛型实现)(转)
C#笔记25:比较和排序(IComparable和IComparer以及它们的泛型实现) 本文摘要: 1:比较和排序的概念: 2:IComparable和IComparer: 3:IComparabl ...
- C#的 IComparable 和 IComparer接口及ComparableTo方法的 区别(非常重要)
(1)https://blog.csdn.net/ios99999/article/details/77800819 C# IComparable 和 IComparer 区别 (2)https:// ...
- 对象的比较与排序:IComparable和IComparer接口
IComparable和ICompare 接口是.net framework 中比较对象的标准方式,这两个接口提供一个返回值类似(大于0 等于0 小于0)的比较方法,二者区别如下: . ICompar ...
随机推荐
- 使用 EnumWindows 找到满足你要求的窗口 - walterlv
原文:使用 EnumWindows 找到满足你要求的窗口 - walterlv 使用 EnumWindows 找到满足你要求的窗口 2019-04-30 13:11 在 Windows 应用开发中,如 ...
- ROS报错:IOError:[Errno 13]permission denied: /home/neousys/.ros/roscore-11311.pid"
在安装ROS后启动ROS,输入:roscore 时报错: 这个问题是由于该路径下ros文件权限造成的. 输入以下命令修改权限: sudo chmod -R ~/.ros/ 修改完成后再次输入rosco ...
- @topcoder - SRM697D1L3@ ConnectedStates
目录 @description@ @solution@ @accepted code@ @details@ @description@ 有n个城市,每个城市有个权值wi,任意两个城市i,j之间的道路数 ...
- @雅礼集训01/06 - T3@ math
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给出 n, m, x,你需要求出下列式子的值: \[\sum_{ ...
- 在 Linux 安装 IIS?
在 Linuxe 安装 IIS? 在群里有人说他的老大让他在 Linux 中安装 IIS. 一群人回复不同的解决方案. 在 Linux 安装虚拟机,再安装 Windows. (哈哈哈) 这个问题虽然有 ...
- 【BestCoder Round #93 1004】MG loves set
[题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=6022 [题意] 让你求一个集合的子集数目; 这个子集有要求; 即: 它所有元素的平方的和小于它所有 ...
- 最全Pycharm教程(43)——Pycharm扩展功能之UML类图使用 代码结构
版权声明:本文为博主原创文章,转载时麻烦注明源文章链接,谢谢合作 https://blog.csdn.net/u013088062/article/details/50353202 1.什么是UML ...
- Innodb_large_prefix
innodb_large_prefix Prefixes, defined by the length attribute, can be up to 767 bytes long for InnoD ...
- HTML提供的6种空格
HTML提供了6种空格(space entity),它们拥有不同的宽度. 非断行空格( )是常规空格的宽度,可运行于所有主流浏览器.其它几种空格( . . ..)在不同浏览器中宽度各异. ...
- python编程设计模式之接口类和抽象类
接口类 """ 接口类 是一种编程设计模式,在python原本没有接口类 借用Java思想创建的一种规范设计模式 支持多继承,进行多方面规范 ""&q ...