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. App Store生存指南

    资格获取   如果已经有App Store开发帐号请跳过此节.   App Store的资格获取其实一直以来都不算难,和其它事情一样,需要的只是耐心.现在苹果对申请者的文书手续要求已经比几年前简化多了 ...

  2. Egret HTTP网络

    HTTP 请求与响应: private createGameScene():void { //HTTP 1.0 var request = new egret.HttpRequest(); reque ...

  3. google chrome中如何删除一条输入网址提示

    在google chrome中网站栏输入字母的时候会出现网址的提示,如下图: 之前遇到个问题,不知道之前打错了www.baidu.com为wwww.baidu.com(也会跳转到百度)导致一输入“w” ...

  4. MVC身份验证及权限管理

    MVC自带的ActionFilter 在Asp.Net WebForm的中要做到身份认证微软为我们提供了三种方式,其中最常用的就是我们的Form认证,需要配置相应的信息.例如下面的配置信息: < ...

  5. 应用Oracle(Linux中的安装)

    Linux中安装Oracle,不同于windows. Linux在安装时,要作些必要的分区配置,以便进行Oracle的安装: 同时需要创建专门的数据库用户和组,并配置环境变量. root登录 使用 r ...

  6. 使用单调队列优化的 O(nm) 多重背包算法

    我搜索了一下,找到了一篇很好的博客,讲的挺详细:链接. 解析 多重背包的最原始的状态转移方程: 令 c[i] = min(num[i], j / v[i]) f[i][j] = max(f[i-1][ ...

  7. SQL Server 中的嵌套事务与@@TranCount(转)

    在处理事务的时候,一般都用RollBack Transaction来回滚,但是如果在嵌套事务中这样使用的话,就会出现错误. 在SqlServer里,嵌套事务的层次是由@@TranCount全局变量反映 ...

  8. JAVA NIO 简介(转)

    1.   基本 概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系统提供执行 I/O 较高级 ...

  9. MySql的大小写问题

    原来Linux下的MySQL默认是区分表名大小写的,通过如下设置,可以让MySQL不区分表名大小写:1.用root登录,修改 /etc/my.cnf:2.在[mysqld]节点下,加入一行: lowe ...

  10. Unity NGUI实现按钮点击播放Aniamtion

    unity版本:4.5 NGUI版本:3.6.5 参考链接:http://www.colabug.com/thread-1029974-1-1.html,作者:COLABUG.COM 橘虞 1.怎么创 ...