上一篇文章介绍了使用IComparable接口和IComparer接口比较对象,然后对该类型的对象列表进行排序,这里的区别是可以使用IComparable和IComparer泛型接口。要对List<T>排序,可以再排序的类型上实现IComparable<T>泛型接口或定义IComparer<T>泛型接口。
不过这里介绍泛型委托实现对List<T>排序。
一般情况下,给列表排序需要提供一个方法来比较两个T类型的对象。要在列表中搜索,需要提供一个检查T类型的方法,看看它是否满足某个条件,这里给出两个可以使用的泛型委托类型。
Comparison<T>:这个泛型委托类型用于排序方法,返回类型和参数如下:
int method(T object1, T object2)
Predicate<T>:这个泛型委托类型用于搜索方法,返回类型和参数如下:
bool method(T object)
示例如下:
创建一个控制台程序,添加一个Vector类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CH12Ex03test
{
public class Vector
{
public double? R = null; //定义可控类型矢量模长
public double? Theta = null; //定义可控类型矢量角度
public double? ThetaRadians //定义可控类型矢量弧度
{
get
{
return (Theta * Math.PI / 180.0);
}
}
public Vector(double? r, double? theta)
{
if (r<0)
{
r = -r;
theta += 180.0;
}
theta %= 360;
R = r;
Theta = theta;
}
public static Vector operator +(Vector op1, Vector op2)
{
try
{
double newX = op1.R.Value * Math.Sin(op1.ThetaRadians.Value) + op2.R.Value * Math.Sin(op2.ThetaRadians.Value);
double newY = op2.R.Value * Math.Cos(op2.ThetaRadians.Value) + op2.R.Value * Math.Cos(op2.ThetaRadians.Value);
double newR = Math.Sqrt(newX * newX + newY * newY);
double newTheta = Math.Atan2(newX, newY) * 180.0 / Math.PI;
return new Vector(newR, newTheta);
}
catch
{
return new Vector(null, null);
}
}
public static Vector operator -(Vector op)
{
return new Vector(-op.R, op.Theta);
}
public static Vector operator -(Vector op1, Vector op2)
{
return op1 + (-op2);
}
}
}
然后定义一个集合类Vectors,可以使用List<Vectors>类型,但由于要定义其他方法,因此继承List<Vectors>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CH12Ex03test
{
public class Vectors : List<Vector>
{
public Vectors()
{
}
public Vectors(IEnumerable<Vector> initItems) //在测试代码中会使用List<Vector>.FindAll()方法返回List<Vector>来初始化Vectors对象,
{ //因此这里要增加这个非默认构造函数
foreach (Vector vec in initItems)
{
Add(vec);
}
}
public StringBuilder Sum()
{
StringBuilder sb = new StringBuilder();
Vector currentPt = new Vector(0.0, 0.0);
sb.AppendFormat("({0},{1})", currentPt.R, currentPt.Theta);
foreach(Vector vec in this)
{
currentPt = currentPt + vec;
sb.AppendFormat("+({0},{1})", vec.R, vec.Theta);
}
sb.AppendFormat("=({0},{1})", currentPt.R, currentPt.Theta);
return sb;
}
}
}
定义一个委托类型和它的分别用于排序和搜索的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CH12Ex03test
{
public static class VectorDelegates
{
public static int Order(Vector vec1, Vector vec2)
{
if (vec1.R > vec2.R)
{
return 1;
}
else if (vec1.R < vec2.R)
{
return -1;
}
else
{
return 0;
}
}
public static bool Search(Vector vec)
{
if (vec.Theta > 0)
{
return true;
}
else
{
return false;
}
}
}
}
测试代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CH12Ex03test
{
class Program
{
static void Main(string[] args)
{
StringBuilder strResult;
Vectors vectors = new Vectors();
vectors.Add(new Vector(3.0, 45.0));
vectors.Add(new Vector(6.0, -60.0));
vectors.Add(new Vector(5.0, -30.0));
vectors.Add(new Vector(2.0, 20.0));
Console.WriteLine("矢量相加求和");
strResult = vectors.Sum();
Console.WriteLine(strResult);
Console.WriteLine("按矢量模长排序后矢量相加求和");
Comparison<Vector> sorter = new Comparison<Vector>(VectorDelegates.Order);
vectors.Sort(sorter);
strResult = vectors.Sum();
Console.WriteLine(strResult);
Console.WriteLine("只保留角度大于0的矢量");
Predicate<Vector> searcher = new Predicate<Vector>(VectorDelegates.Search);
Vectors restVectors = new Vectors(vectors.FindAll(searcher));
strResult = restVectors.Sum();
Console.WriteLine(strResult);
Console.ReadKey();
}
}
}
运行结果,可以看到首次矢量相加按照对象添加到集合类中的顺序计算矢量和,第二次矢量相加先对各矢量对象按模长进行排序再求和,最后一次是只保留角度大于0的矢量求和: