Icomparer和Icomparable用法浅谈

c#中实现对象实例的比较有两个常用接口即Icomparer和Icomparable,今天对其进行整理。


1.首先解释一下comparer和comparable两个单词的意思,这对两个接口的理解有所帮助。

comparable:是可比较,那么实现Icomparable接口自然是说这个类的实例是可以比较的。

comparer:英文中没有这个词,但从字面可以理解它是比较器的意思,那么实现Icomparer接口自然是说这个类是起到一个比较器的作用。


2.c#中实现对象集合的排序可以使用ArrayList中的Sort()方法,而有比较才能谈排序,因为不是基本类型(如string ,int.double......等)所以.NET Framework不可能一一制定他们的比较规则,那么则需要程序员自行制定,而比较规则的制定就需要通过继承这两个接口之一来实现。制定了比较规则后则才可以用以下两种方式之一调用排序:

(1)ArrayList实例.Sort();

(2)ArrayList实例.Sort(实现Icomparer接口的类);


3.通过完整示例来演示两个接口的用法:

(1)首先定义一个Person类,其中包含一个构造函数,两个私有字段,两个共有属性。
Icomparer和Icomparable用法浅谈 - Improve - Improve Icomparer和Icomparable用法浅谈 - Improve - Improve
  (2)在main函数中添加Person类的对象集合People,并创建4个person类,将其一一加入People集合中

Icomparer和Icomparable用法浅谈 - Improve - Improve
 (3)使用Icomparable接口制定比较规则:
comparable的意思是可比较,那么只要实现Icomparable接口,这个类的实例就可以进行比较了,那么如何使用Icomparable接口制定比较规则呢,只需要在要类中实现Icomparable接口中的CompareTo(object obj)函数即可。其中参数obj便是要与当前类实例进行比较的对象。

接口实现:
Icomparer和Icomparable用法浅谈 - Improve - Improve
PS: 1.你也许会问为什么参数不直接写为Person myperson,因为这是接口的实现,是重写而不是重载,所谓重写就是要函数签名一致。
        2.而且用as运算符将myobject转换为Person也是必须的,因为Age是Person中的属性,而object是他的父类。否则会出错。
        3.后面调用的Sort()是根据比较返回的int值进行排序的,如果比较函数调用者返回值大于0这个实例排在被比较者之后,那么也就是所默认递增排序,要递减排序只需要改动返回值即可       Icomparer和Icomparable用法浅谈 - Improve - Improve

函数调用:
Icomparer和Icomparable用法浅谈 - Improve - Improve

运行结果:
           Icomparer和Icomparable用法浅谈 - Improve - Improve
  
  (4)使用Icompare接口制定比较规则:
compare的意思是比较器,那么实现这个接口的类就是一个比较器 ,而Sort()的重载之一就是在参数中加入一个比较器,用来比较两个对象的大小。即Sort(实现Icompare接口的实例)    。
比较器的实现:
Icomparer和Icomparable用法浅谈 - Improve - Improve 
 PS:1.其中声明的静态字段Default的作用只是创建一个PersonComparer类,方便使用,可以不这样写,只不过调用方法会改变,稍后说明。
        2.其中运用的Comparer.Default.Compare()函数式System.Collections.中的Comparer中的一个比较基本类型的大小的函数,因为我们比较的是基本类型string所以不必自己再写。而Comparer.Default正和我们的Default字段是一样的含义,只是创建一个Comparer对象,以便引用其中的基本类型的比较函数Compare()。

方法调用:
Icomparer和Icomparable用法浅谈 - Improve - Improve
 PS:1.Sort()中的参数是一个比较器(即实现了Icompare几口的实例)如果类中没有定义Default字段那么这里就要通过new PersonComparer()来创建PersonComparer()实例,结果是一样的。

运行结果:
Icomparer和Icomparable用法浅谈 - Improve - Improve
 如果要递减只需要在返回结果上面乘以-1即可。
 
以下是完整代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //新建集合people用来存放person实例 ArrayList people = new ArrayList(); //建立4个person实例 Person person1 = new Person("Jone", 18); Person person2 = new Person("Tom", 20); Person person3 = new Person("Lily", 15); Person person4 = new Person("July", 25); //将实例添加到people集合中 people.Add(person1); people.Add(person2); people.Add(person3); people.Add(person4); //输出原来序列 Console.WriteLine("原来序列:"); foreach (Person person in people) { Console.WriteLine("person name: {0} age:{1}", person.Name, person.Age); } //用实现Icomparable进行排序 people.Sort(); //用实现Icomparable的方法输出排序后的序列 Console.WriteLine("排序后的序列:"); foreach (Person person in people) { Console.WriteLine("person name: {0} age:{1}", person.Name, person.Age); } //用实现Icomparer的方法进行排序 people.Sort(PersonComparer.Default); //用实现Icomparer的方法输出排序后的序列 Console.WriteLine("排序后的序列:"); foreach (Person person in people) { Console.WriteLine("person name: {0} age:{1}", person.Name, person.Age); } Console.ReadKey(); } } public class Person:IComparable { /// <summary> /// 两个私有字段: /// 人物姓名; /// 人物年龄; /// </summary> private string name; private int age; /// <summary> /// 构造函数 /// </summary> public Person(string myname,int myage) { name = myname; age = myage; } /// <summary> /// 两个共有属性: /// 分别对应两个私有字段; /// </summary> public string Name { set { name = value; } get { return name; } } public int Age { set { age = value; } get { return age; } } public int CompareTo(object myobject) { if (myobject is Person)//用is运算符判断要比较的对象是否是Person对象 { //如果是用as运算符进行对象转换,返回年龄比较结果(一个整数,表示两者差) Person myperson = myobject as Person; return this.Age - myperson.Age; //return myperson.Age - this.Age; } else { //如果不是,抛出异常 throw new ArgumentException("Object to compare to is not a Person Object"); } } } public class PersonComparer : IComparer { //静态字段,方便使用,没有也可,调用方法会变 public static IComparer Default = new PersonComparer(); public int Compare(object myperson1, object myperson2) { //用is运算符判断要比较的对象是否都是Person对象 if (myperson1 is Person && myperson2 is Person) { //如果是,调用.Net Framework已经实现好的能比较基本类型的函数:Comparer.Default.Compare //(要用using System.Collections;) return Comparer.Default.Compare((Person)myperson1, (Person)myperson2); } else { //如果不是抛出异常 throw new ArgumentException("One or both objects to compare are not Person objects."); } } } }





 

 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值