IComparable接口

  System.IComparable接口指定了一种允许一个对象可基于某些特定键值进行排序的行为。

namespace System
{
[ComVisible(true)]
public interface IComparable
{
int CompareTo(object obj);
}
}

CompareTo()方法背后的逻辑是,根据某个特定数据字段比较传入的对象与当前实例。CompareTo()方法的返回值被用来判断这个类型小于、大于或是等于它所比较的对象。

  • 任何小于0的数字:这个实例在指定对象之前
  • 0:这个实例等于指定对象
  • 任何大于0的数字:这个实例在指定对象之后

构建可比较对象

  System.Array类定义了一个名为 Sort()的静态方法。在内置类型(int、short、string等)上调用这个方法的时候,可以以数字/字母顺序对数组中的项排序,因为这些内置数据类型实现了IComparable。

构建可排序的Car类型

namespace ComparableCar
{
class Car : IComparable
{
public int CurrentSpeed { get; set; }
public string PetName { get; set; }
public int CarID { get; set; }
public Car() { } public Car( string name, int currSp, int id )
{
CurrentSpeed = currSp;
PetName = name;
CarID = id;
} int IComparable.CompareTo(object obj)
{
Car temp = obj as Car;
if (temp != null)
{
if (this.CarID > temp.CarID)
return ;
if (this.CarID < temp.CarID)
return -;
else
return ;
}
else
throw new ArgumentException("Parameter is not a Car!");
}
}
}

  由于C#int数据类型(只是CLR System.Int32的简写形式)实现了IComparable,我们就可以按如下所示的方法实现ICompareTo()方法:

        int IComparable.CompareTo( object obj )
{
Car temp = obj as Car;
if (temp != null)
return this.CarID.CompareTo(temp.CarID);
else
throw new ArgumentException("Parameter is not a Car!");
}

  Car类型已经知道如何将它自己和类似对象进行对比:

namespace ComparableCar
{
class Program
{
static void Main( string[] args )
{
Console.WriteLine("***** Fun with Object Sorting *****\n");
Car[] myAutos = new Car[];
myAutos[] = new Car("Rusty", , );
myAutos[] = new Car("Mary", , );
myAutos[] = new Car("Viper", , );
myAutos[] = new Car("Mel", , );
myAutos[] = new Car("Chucky", , ); Console.WriteLine("Here is the unordered set of cars:");
foreach (Car c in myAutos)
Console.WriteLine("{0} {1}", c.CarID, c.PetName); Array.Sort(myAutos);
Console.WriteLine(); Console.WriteLine("Here is the ordered set of cars:");
foreach (Car c in myAutos)
Console.WriteLine("{0} {1}", c.CarID, c.PetName); Console.ReadLine();
}
}
}

指定多个排序顺序IComparer

  如果要构建一个既可通过ID排序又可通过昵称排序的Car类型,就需要与另一个标准接口IComparer打交道。

namespace System.Collections
{
[ComVisible(true)]
public interface IComparer
{
int Compare(object x, object y);
}
}

  与IComparable接口不同,IComparer接口不是在要排序的类型(即Car)中,而是在许多辅助类中实现的,其中每个排序各有一个依据(如昵称、ID号等)。

namespace ComparableCar
{
// 这个辅助类用来通过昵称排序Car类型的数组
public class PetNameComparer : IComparer
{
// 测试每个对象的昵称
int IComparer.Compare( object o1, object o2 )
{
Car t1 = o1 as Car;
Car t2 = o2 as Car;
if (t1 != null && t2 != null)
return String.Compare(t1.PetName, t2.PetName);
else
throw new ArgumentException("Parameter is not a Car!");
}
}
}

  System.Array有许多重载的Sort()方法,其中有一个用来在对象上实现IComparer接口。

namespace ComparableCar
{
class Program
{
static void Main( string[] args )
{
...
// 按照昵称进行排序
Array.Sort(myAutos, new PetNameComparer()); Console.WriteLine("Ordering by pet name:");
foreach (Car c in myAutos)
Console.WriteLine("{0} {1}", c.CarID, c.PetName);
...
}
}
}

自定义属性、自定义排序类型

  值得指出的是,在通过特定数据字段排序Car类型的时候,可以使用自定义的静态属性辅助对象用户。假定Car类型添加了一个静态只读属性SortByPetName,它返回一个实现了IComparer接口的对象的实例(在本例中为PetNameComparer):

namespace ComparableCar
{
// 现在可以使用一个自定义静态属性来返回正确的IComparer接口
class Car : IComparable
{
...
// 返回SortByPetName比较的属性
public static IComparer SortByPetName
{ get { return (IComparer)new PetNameComparer(); } }
     ...
}
}

  现在可以使用强关联属性按照昵称排序,而不是只能使用独立的PetNameComparer类型:

// 简洁明了的按照昵称排序
Array.Sort(myAutos, Car.SortByPetName);

构建可比较的对象(IComparable)的更多相关文章

  1. WPF整理-XAML构建后台类对象

    1.XAML 接触WPF的第一眼就是XAML---XAML是用来描绘界面的.其实不然! "Actually, XAML has nothing to do with UI. It's mer ...

  2. 从零构建JavaScript的对象系统

    一.正统的类与继承 类是对象的定义,而对象是类的实例(Instance).类不可直接使用,要想使用就必须在内存上生成该类的副本,这个副本就是对象. 以Java为例: public class Grou ...

  3. Android开发 ---构建对话框Builder对象,消息提示框、列表对话框、单选提示框、多选提示框、日期/时间对话框、进度条对话框、自定义对话框、投影

    效果图: 1.activity_main.xml 描述: a.定义了一个消息提示框按钮 点击按钮弹出消息 b.定义了一个选择城市的输入框 点击按钮选择城市 c.定义了一个单选提示框按钮 点击按钮选择某 ...

  4. JS批量获取参数构建JSON参数对象

    在做系统的时候,往往查询条件是被严格指定的,大量的查询条件,一两个页面还可以通过dom去一个一个获取,再构建参数对象,请求后台接口. 这里给大家讲一个批量获取前端参数,构建参数对象. <form ...

  5. 使用SQL联合查询来构建临时vo对象的应用

    联合查询: 表1: team球队表 表2:schedule 赛程表 需要数据: 球队名称.主队ID.主队名称.客队ID.客队名称.胜负情况 方法1. Object数组取出列和数值 import jav ...

  6. spring mvc 利用匿名内部类构建返回json对象

    @RequestMapping(value = "/order/findOrderByIdVague/{noId}.json", method = {RequestMethod.G ...

  7. 调用的方法里接收一个List<>类型的参数,里面是自定义的EC类, 我要通过反射构建这List对象

              public static object CreateGeneric(Type generic, Type innerType, params object[] args)     ...

  8. 精通C#(第6版)

    <精通C#(第6版)> 基本信息 原书名:Pro C# 5.0 and the .NET 4.5 framework,sixth edition 作者: (美)Andrew Troelse ...

  9. .NET 接口

    接口      接口是一组抽象成员的集合,表示某个类或结构可以选择去实现的行为,描述的是可属于任何类或结构的一组相关功能.接口方法的实现是在实现接口的类中完成的,实现接口的类可以显式实现该接口的成员, ...

随机推荐

  1. 编译内核出错:invalid option `abi=aapcs-linux' 解决办法

    出现此问题的原因是由于kernel feature中选中了Use the ARM EABIto compile the kernel引起的,有两各解决办法: 1)换编译器为arm-linux-gcc ...

  2. 轻松解决Win8.1连接受限或无法连接WiFi问题

    在无线网络连接设置窗口中,找到当前连接的无线网络“WLAN状态”,右击查看“状态”. 在“WLAN状态”窗口中找到“无线属性”. 进入“无线网络属性”窗口,切换到“安全”页面,点击“高级设置”.最重要 ...

  3. BZOJ 1036 树的统计

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...

  4. Parencodings

    Description Let S = s1 s2...s2n be a well-formed string of parentheses. S can be encoded in two diff ...

  5. Mysql中类似于nvl()函数的ifnull()函数

    IFNULL(expr1,expr2) 如果expr1不是NULL,IFNULL()返回expr1,否则它返回expr2.IFNULL()返回一个数字或字符串值,取决于它被使用的上下文环境. mysq ...

  6. 2.JQuery AJAX

    new ActiveXObject("Microsoft XMLHTTP")是IE中创建XMLHTTPRequest对象的方法.非IE浏览器创建方法是new XmlHttpRequ ...

  7. 利用over开窗函数取第一条记录

    SQL> set linesize 200 SQL> select * from (select a.* ,row_number() over( order by empno) rn  f ...

  8. Apache HTTP Server mod_dav.c 拒绝服务漏洞(CVE-2013-1896)

    漏洞版本: Apache HTTP Server < 2.2.25 漏洞描述: CVE ID:CVE-2013-1896 Apache HTTP Server是一款流行的WEB服务器 Apach ...

  9. HDU 1523 Decoding Morse Sequences

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1523 此题大意为 给你一串摩尔斯密码  再给你一个字典(下面单词本) 用下面的单词组合成给你的摩尔斯密 ...

  10. 网络流(最大流):POJ 1149 PIGS

    PIGS Time Limit: 1000ms Memory Limit: 10000KB This problem will be judged on PKU. 64-bit integer(整数) ...