详解C# IComparable和IComparer接口和自定义比较器

 更新时间:2025年07月27日 10:17:12   作者:My_Pure  
本文主要介绍了详解C# IComparable和IComparer接口和自定义比较器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

ArrayList里面有一个方法:

public virtual void Sort(IComparer comparer);
使用指定的比较器对整个 System.Collections.ArrayList 中的元素进行排序。
comparer:比较元素时要使用的 System.Collections.IComparer 实现。

啥玩意啊?

1.Comparer类简单介绍

想弄清楚这个,我们先来看看这么一个类。
在System.Collections名称空间中,有这么一个类:Comparer。顾名思义,他可以实现对简单类型的比较,什么意思呢?来看如下代码:

int a=1,b=2;

正常情况下,我们要怎样比较他们的大小?if,运算符,……?这当然可以,不过Comparer已经给我们提供了一个函数,可以直接使用:(需要using System.Collections;)

Console.WriteLine(Comparer.Default.Compare(a,b));

因为a<b,所以控制台会输出-1。(这个函数总是返回-1,0,1三个值。)
这里通过Comparer里的静态属性Default获得Comparer的实例调用了Comparer里的非静态函数Compare。
(还可以比较根据字母比较两个string类型,这里就省略介绍了)

2.自定义比较器,IComparable,IComparer接口

当然,这个类不仅仅只是用来比较两个数的大小的。有时候我们想直接比较两个对象,但是引用里面的属性或许比较麻烦。尤其是参考要素过多,不好直接比较的时候,怎样才能更高效地比较两个对象呢?这时候,我们就需要自定义比较器了。
首先来介绍IComparable接口。这个接口里只有一个方法CompareTo()。让你的类实现这个接口的CompareTo方法,就可以直接调用这个方法和另一个对象比较。下面是例子:

public class ClassTest : IComparable
{
  public int intTest;
  public int CompareTo(object obj)
  {
    return intTest-((ClassTest)obj).intTest;
    //这里的代码可以按需要自己编写,这里只是一个简单的示例
  }
}

然后就可以直接使用啦:

ClassTest a = new ClassTest(){intTest=1};
ClassTest b = new ClassTest(){intTest=2};
Console.WriteLine(a.CompareTo(b));//输出-1

Comparer类已经为我们提供了IComparer的默认实现,但我们仍然可以自定义它。新建一个类:(记得using System.Collections;)

public class ClassTestComparer : IComparer
{
  public static IComparer Default = new ClassTestComparer();
  //这里必须使用这样的定义,将对象转化为IComparer类型有很大用处,下面会介绍
  public int Compare(object a,object b)
  {
    return ((ClassTest)a).intTest - ((ClassTest)b).intTest;
    //同样这里使用最简单的示例,但是你可以大放异彩
  }
}

注意,如果用于比较的类和设定的类不一样,就会出现错误。
使用示例:

ClassTest a = new ClassTest(){intTest=1};
ClassTest b = new ClassTest(){intTest=2};
Console.WriteLine(ClassTestComparer.Default.Compare(a,b));
//结果是-1

可以发现,这两个接口的不同之处在于:IComparable在要比较的对象的类中实现,可以比较该对象和另一个对象。IComparer在一个单独的类中实现,可以比较任意两个对象(关键是你的设置)。

3.对集合排序

当然,这两个接口还有更强大的用处。我们可以使用这两个接口对集合进行排序。还记得前言里的Sort()方法吗?接下来就以ArrayList为例,介绍如何使用。

ArrayList ClassTests = new ArrayList();
ClassTest a = new ClassTest(){intTest=1};
ClassTest b = new ClassTest(){intTest=2};
ClassTest c = new ClassTest(){intTest=3};
ClassTests.Add(a);
ClassTests.Add(b);
ClassTests.Add(c);
ClassTests.Sort();
//使用无参的Sort,将调用类中的CompareTo()方法,因为ClassTest实现了这个方法,所以是可以调用的。如果没有实现,编译器会报错。
ClassTests.Sort(ClassTestComparer.Default);
//这将使用Compare()方法对集合中的元素排序。ClassTestComparer类实现了这个方法,并且提供了一个IComparer类型的属性。

需要注意的是:

  • 两个接口提供的方法返回值都是int类型的,负数代表小于,0代表等于,正数代表大于。所以对数字之外的自定义比较器,需要人工设定什么是“大”,什么是“小”。所以上文示例中两个数直接相减,就可以比较大小。
  • 排序完之后,按照返回的int值,集合是由小到大排列的。
  • 使用无参Sort()时,集合中至少要有一个类实现了IComparable,否则会报错。
  • 一般来说,都是对同一个类进行比较。不过,也可以实现对不同类比较的代码,这就看具体需要了。

到此这篇关于详解C# IComparable和IComparer接口和自定义比较器的文章就介绍到这了,更多相关C# IComparable IComparer内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • unity实现虚拟摇杆控制Virtual Joystick

    unity实现虚拟摇杆控制Virtual Joystick

    这篇文章主要为大家详细介绍了unity实现虚拟摇杆控制Virtual Joystick,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C#实现移动窗体的两种共方法

    C#实现移动窗体的两种共方法

    在C#Form窗体设计中,如果我们不需要使用默认边框设计自己个性化的窗体,这时候你会发现拖动窗体的功能就没有了,这里需要自己构建方法让用户可以拖动整个窗体,下面就介绍两种方法来实现,需要的朋友可以参考下
    2024-09-09
  • C#实现位图转换成图标的方法

    C#实现位图转换成图标的方法

    这篇文章主要介绍了C#实现位图转换成图标的方法,可实现将bmp格式位图转换成ico格式图标的功能,需要的朋友可以参考下
    2015-06-06
  • c#完美截断字符串代码(中文+非中文)

    c#完美截断字符串代码(中文+非中文)

    c#完美截断字符串代码(中文+非中文),需要的朋友可以参考下
    2012-08-08
  • winform实现创建最前端窗体的方法

    winform实现创建最前端窗体的方法

    这篇文章主要介绍了winform实现创建最前端窗体的方法,涉及C#窗体属性设置的相关技巧,非常具有实用价值,需要的朋友可以参考下
    2015-08-08
  • C#中使用Join与GroupJoin将两个集合进行关联与分组

    C#中使用Join与GroupJoin将两个集合进行关联与分组

    这篇文章主要介绍了C#中使用Join与GroupJoin将两个集合进行关联与分组,文中分别对Join和GroupJoin的用法进行详细说明,需要的朋友可以参考下
    2017-12-12
  • C#如何给PDF文件添加水印

    C#如何给PDF文件添加水印

    这篇文章主要为大家详细介绍了C#如何给PDF文件添加水印的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • C#中关于double.ToString()的用法

    C#中关于double.ToString()的用法

    这篇文章主要介绍了C#中关于double.ToString()的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 访问修饰符(C# 编程指南)

    访问修饰符(C# 编程指南)

    所有类型和类型成员都具有可访问性级别,用来控制是否可以在您程序集的其他代码中或其他程序集中使用它们。您在声明类型或成员时使用以下访问修饰符之一来指定其可访问性
    2011-02-02
  • C#中的递归APS和CPS模式详解

    C#中的递归APS和CPS模式详解

    这篇文章主要介绍了C#中的递归APS和CPS模式详解,本文讲解了累加器传递模式、CPS函数、CPS变换、CPS尾递归、尾递归与Continuation等内容,需要的朋友可以参考下
    2015-04-04

最新评论