您的位置:首页 > Web前端

Effective C# 学习笔记(三十一)利用IComparable<T>和IComparer<T>接口来实现排序关系

2011-07-17 21:13 706 查看
你的类型需通过描述在集合中该类型的对象该如何排序和被查找来说明其排序关系。

.NET framework中定义了IComaprable<T>和IComparer<T>接口来为你的类型定义排序关系。

前者定义了你类型的自然排序方式,后者则定义了其他的排序方式(通过<,>,<=,>=等运算关系的定义来提高在运行时的比较性能)。

IComparable<T>接口包含一个CompareTo()方法(该方法的时间复杂度平均为n
lg(n)),该方法返回0时该对象和比较对象相等,返回小于0的值时则该对象小于比较对象,返回大于0值时该对象大于比较对象。而为了和一些旧的APIs相兼容,你需要同时实现IComparable非范型比较接口,该接口的CompareTo接受Object对象类型参数,所以你要对类型进行转换检查。下面的代码是一个简单的实现:

public struct
Customer : IComparable<Customer>, IComparable

{

private
readonly string name;

public
Customer(string name)

{

this.name
= name;

}

#region
IComparable<Customer> Members

public
int CompareTo(Customer other)

{

return
name.CompareTo(other.name);

}

#endregion

#region
IComparable Members

int
IComparable.CompareTo(object obj)

{

if
(!(obj is Customer))

throw
new ArgumentException(

"Argument
is not a Customer", "obj");

Customer
otherCustomer = (Customer)obj;

return
this.CompareTo(otherCustomer);

}

#endregion

}

出了实现Icomparable<T>和IComparable接口外,你还可以定义比较运算符来给客户端提供更方便的比较方式,代码如下:

public struct
Customer : IComparable<Customer>, IComparable

{

private
readonly string name;

public
Customer(string name)

{

this.name
= name;

}

#region
IComparable<Customer> Members

public
int CompareTo(Customer other)

{

return
name.CompareTo(other.name);

}

#endregion

#region
IComparable Members

int
IComparable.CompareTo(object obj)

{

if
(!(obj is Customer))

throw
new ArgumentException(

"Argument
is not a Customer", "obj");

Customer
otherCustomer = (Customer)obj;

return
this.CompareTo(otherCustomer);

}

#endregion

//
Relational Operators.

public
static bool operator <(Customer left,Customer right)

{

return
left.CompareTo(right) < 0;

}

public
static bool operator <=(Customer left,Customer right)

{

return
left.CompareTo(right) <= 0;

}

public
static bool operator >(Customer left,Customer right)

{

return
left.CompareTo(right) > 0;

}

public
static bool operator >=(Customer left,Customer right)

{

return
left.CompareTo(right) >= 0;

}

}

通过创建静态属性来提供非标准的排序支持定义,代码如下:

public static
Comparison<Customer> CompareByReview

{

get

{

return
(left,right) => left.revenue.CompareTo(right.revenue);

}

}

而一些旧的类库需要通过实现IComparer接口的功能,来提供非标准的排序定义。注意:这种通过创建辅助排序类来定义排序的方式建议只在你没有权限访问到原有类型的源码时使用。代码如下:

//1. 先定义一个继承自IComparer<T>接口的类型:

// Class to compare
customers by revenue.

// This is always
used via the interface pointer,

// so only provide
the interface override.

private class
RevenueComparer : IComparer<Customer>

{

#region
IComparer<Customer> Members

int
IComparer<Customer>.Compare(Customer left,Customer right)

{

return
left.revenue.CompareTo(

right.revenue);

}

#endregion

}

//2. 定义该类型的静态属性,单例形式创建

private static
RevenueComparer revComp = null;

// return an object
that implements IComparer

// use lazy
evaluation to create just one.

public static
IComparer<Customer> RevenueCompare

{

get

{

if
(revComp == null)

revComp
= new RevenueComparer();

return
revComp;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: