前面说到,我们可以使用 IComparer<T> 和 IComparable<T> 接口比较两个对象,然后对该类型的对象列表排序。现在我们来介绍另两个委托可以来用排序和搜索列表
先总结一下前面的内容:
MSDN上List有如下的sort重载:
如果调用无参的sort()方法,那么要求集合中的元素要实现 System.IComparable 接口,否则此方法会抛出InvalidOperationException异常。
如果集合的元素没有实现IComparable接口,则可以调用Sort(IComparer<T>),这时我们要创建一个类实现IComparer接口作为比较器来完成排序。
或者更为简单些,不需要定义一个比较器,直接给sort方法提供一个用于"比较两对象”大小的方法即可---实现Comparison<T>委托。
可以参见另一日记:
一般情况下,给列表排序需要有一个方法来比较T类型的两个对象。要在列表中搜索,也需要一个方法来检查T类型的对象,看看它是否满足某个条件。定义这样的方法很简单,这里给出两个可以使用的泛型委托。
1. Comparision<T> 这个委托类型用于排序方法,其返回类型和参数是 int method(T object A , T objectB)
2.Predicate<T> 这个委托类型用于搜索方法,其返回类型和参数是 bool method(T targetObject).
可以定义任意个这样的方法,使用它们实现 List<T> 的搜索和排序方法。
定义一个Vector类
public class Vector { public double? R = null; public double? Theta = null; public double? ThetaRadians { get { // Convert degrees to radians. return (Theta * Math.PI / 180.0); } } public Vector(double? r, double? theta) { // Normalize. if (r < 0) { r = -r; theta += 180; } theta = theta % 360; // Assign fields. R = r; Theta = theta; } public static Vector operator +(Vector op1, Vector op2) { try { // Get (x, y) coordinates for new vector. double newX = op1.R.Value * Math.Sin(op1.ThetaRadians.Value) + op2.R.Value * Math.Sin(op2.ThetaRadians.Value); double newY = op1.R.Value * Math.Cos(op1.ThetaRadians.Value) + op2.R.Value * Math.Cos(op2.ThetaRadians.Value); // Convert to (r, theta). double newR = Math.Sqrt(newX * newX + newY * newY); double newTheta = Math.Atan2(newX, newY) * 180.0 / Math.PI; // Return result. return new Vector(newR, newTheta); } catch { // Return "null" vector. return new Vector(null, null); } } public static Vector operator -(Vector op1) { return new Vector(-op1.R, op1.Theta); } public static Vector operator -(Vector op1, Vector op2) { return op1 + (-op2); } public override string ToString() { // Get string representation of coordinates. string rString = R.HasValue ? R.ToString() : "null"; string thetaString = Theta.HasValue ? Theta.ToString() : "null"; // Return (r, theta) string. return string.Format("({0}, {1})", rString, thetaString); } }
下面定义一个集合类 Vectors
public class Vectors : List{ public Vectors() { } public Vectors(IEnumerable initialItems) { foreach (Vector vector in initialItems) { Add(vector); } } public string Sum() { StringBuilder sb = new StringBuilder(); Vector currentPoint = new Vector(0.0, 0.0); sb.Append("origin"); foreach (Vector vector in this) { sb.AppendFormat(" + {0}", vector); currentPoint += vector; } sb.AppendFormat(" = {0}", currentPoint); return sb.ToString(); } }
下面就是我们要定义的用于排序和搜索的方法。
public static class VectorDelegates { public static int Compare(Vector x, Vector y) { if (x.R > y.R) { return 1; } else if (x.R < y.R) { return -1; } return 0; } public static bool TopRightQuadrant(Vector target) { if (target.Theta >= 0.0 && target.Theta <= 90.0) { return true; } else { return false; } } }
下面是测试代码。
class Program { static void Main(string[] args) { Vectors route = new Vectors(); route.Add(new Vector(2.0, 90.0)); route.Add(new Vector(1.0, 180.0)); route.Add(new Vector(0.5, 45.0)); route.Add(new Vector(2.5, 315.0)); Console.WriteLine(route.Sum()); Comparisonsorter = new Comparison (VectorDelegates.Compare); route.Sort(sorter); Console.WriteLine(route.Sum()); Predicate searcher = new Predicate (VectorDelegates.TopRightQuadrant); Vectors topRightQuadrantRoute = new Vectors(route.FindAll(searcher)); Console.WriteLine(topRightQuadrantRoute.Sum()); Console.ReadKey(); } }
1、关于 Predicate<T> 更详细用法,参见
2、可以参见上一个日记,可以用Lamda表达式来使代码更简洁。