使用IComparer进行排序

我正在尝试使用IComparer来对点列表进行排序。 这是IComparer类:

 public class CoordinatesBasedComparer : IComparer { public int Compare(Object q, Object r) { Point a = (p)q; Point b = (p)r; if ((ax == bx) && (ay == by)) return 0; if ((ax < bx) || ((ax == bx) && (ay < by))) return -1; return 1; } } 

在客户端代码中,我试图使用此类来排序点列表p( List类型):

 CoordinatesBasedComparer c = new CoordinatesBasedComparer(); Points.Sort(c); 

代码出错了。 显然它期望IComparer作为sort方法的参数。
我需要做些什么来解决这个问题?

您需要实现强类型接口( MSDN )。

 public class CoordinatesBasedComparer : IComparer { public int Compare(Point a, Point b) { if ((ax == bx) && (ay == by)) return 0; if ((ax < bx) || ((ax == bx) && (ay < by))) return -1; return 1; } } 

顺便说一句,我认为你使用了太多的括号,我相信只有当他们为编译器做出贡献时才应该使用它们。 这是我的版本:

 if (ax == bx && ay == by) return 0; if (ax < bx || (ax == bx && ay < by)) return -1; 

就像我不喜欢使用return (0)


请注意,如果您定位.Net-3.5 +应用程序,则可以使用LINQ,这样可以更轻松,更快速地进行排序。

LINQ vesion可以是这样的:

 var orderedList = Points.OrderBy(point => point.x) .ThenBy(point => point.y) .ToList(); 
 public class CoordinatesBasedComparer : IComparer, IComparer { public int Compare(Point a, Point b) { if ((ax == bx) && (ay == by)) return 0; if ((ax < bx) || ((ax == bx) && (ay < by))) return -1; return 1; } int IComparer.Compare(Object q, Object r) { return Compare((Point)q, (Point)r); } } 

如果你像我一样慢,那么使用IComparer时-1和1很难推理。 考虑它的方法是当x应该先行,返回-1。 当y应该先行时,返回1。

如果你有很多字段需要排序,它仍然会让人感到困惑。 您可以使用Enum使比较逻辑比1和-1更具可读性,然后转换结果。

此示例将前面具有最少量空字段的对象放在前面。

 public class NullishObjectsToTheBackOfTheLine: IComparer { private enum Xy { X = -1, Both = 0, Y = 1 }; //the IComparer implementation wraps your readable code in an int cast. public int Compare(ClassToCompare x, ClassToCompare y) { return (int) CompareXy(x, y); } private static Xy CompareXy(ClassToCompare x, ClassToCompare y) { if (x == null && y == null) return Xy.Both; //put any nulls at the end of the list if (x == null) return Xy.Y; if (y == null) return Xy.X; if (x.Country == y.Country && x.ProductId == y.ProductId) return Xy.Both; //put the least amount of at the front if (x.ProductId == null && x.Country == null) return Xy.Y; if (y.ProductId == null && y.Country == null) return Xy.X; //put the country values that are not nulls in front if (x.Country != y.Country) return x.Country != null ? Xy.X : Xy.Y; //if we got this far, one of these has a null product id and the other doesn't return x.ProductId != null ? Xy.X : Xy.Y; } } public class ClassToCompare { public string Country { get; set; } public string ProductId { get; set; } } 

在将类型为MyClass的对象添加到SortedList我收到了InvalidOperation错误。 我错误地实现了IComparer接口。 我需要实现的是使用CompareTo(MyClass other)方法的IComparable,而不是ICompare.Compare(MyClass x,MyClass y)。 这是一个简化的例子:

 SortedList sortedList = new SortedList(); MyClass a=new MyClass(), b=new MyClass(); sortedList.Add(a); sortedList.Add(b); // Note, sort only happens once second element is added 

这解决了它

 public class MyClass : IComparable { int IComparable.CompareTo(MyClass other) { // DoCompareFunction(this, other); and return -1,0,1 } } 

这被打破了(如果添加到SortedList不要这样做)

 public class MyClass : IComparer { int IComparable.Compare(MyClass x, MyClass y) { // DoCompareFunction(x, y); and return -1,0,1 } } 

这是错误:

无法比较数组中的两个元素。
在System.Collections.Generic.ArraySortHelper`1.BinarySearch(T []数组,Int32索引,Int32长度,T值,IComparer`1比较器)
在System.Array.BinarySearch [T](T []数组,Int32索引,Int32长度,T值,IComparer`1比较器)
在System.Collections.Generic.SortedList`2.Add(TKey键,TValue值)