首先看下List.Sort()方法:
public void Sort(int index, int count, IComparer<T> comparer); //指定范围排序
public void Sort(Comparison<T> comparison);
public void Sort();
public void Sort(IComparer<T> comparer);
一.Comparison<T>
public delegate int Comparison<in T>(T x, T y);
概念:表示用于比较相同类型的两个对象的方法。
- 解释:使用delegate,是为了将方法视为变量并可作为参数传递的实体。
- 对Dictionary 排序:
Dictionary<string, int> dic = new Dictionary<string, int>();
dic.Add("index.html", 50);
dic.Add("product.html", 13);
dic.Add("aboutus.html", 4);
dic.Add("online.aspx", 22);
dic.Add("news.aspx", 18);
//第一种
List<KeyValuePair<string, int>> list1 = new List<KeyValuePair<string, int>>(dic);
list1.Sort(h1);
//第二种
List<KeyValuePair<string, int>> list2 = new List<KeyValuePair<string, int>>(dic);
list1.Sort(delegate (KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
{
return s2.Value.CompareTo(s1.Value);
});
//第三种
List<KeyValuePair<string, int>> list3 = new List<KeyValuePair<string, int>>(dic);
list2.Sort((s1, s2) => { return s1.Value.CompareTo(s2.Value); });
public static int h1(KeyValuePair<string, int> s1, KeyValuePair<string, int> s2)
{
return s2.Value.CompareTo(s1.Value);
}
二. Comparer<T> Class、IComparer<T>
- 概念:为 IComparer<T> 泛型接口实现提供的基类。
public abstract class Comparer<T> : IComparer, IComparer<T>
{
protected Comparer();
public static Comparer<T> Default { get; }
public static Comparer<T> Create(Comparison<T> comparison);
public abstract int Compare(T x, T y);
}
- Comparer<T>和 IComparer<T>的区别:
- Comparer<T>是类,并提供了默认比较器,也就是说,如果需要自定义默认比较器,需要自行实现IComparer<T>接口
- 使用Comparer<T>.Default来获取默认比较器
三. IComparable<T>
与此实例比较的对象
IComparable<T>,实现接口:IComparer<T> IComparer
public interface IComparable<in T>
{
int CompareTo(T other);
}
四.Comparer<T> Class、IComparer<T>、IComparable<T>官方案例
class Test
{
static void Main(string[] args)
{
List<Box> Boxes = new List<Box>();
Boxes.Add(new Box(4, 20, 14));
Boxes.Add(new Box(12, 12, 12));
Boxes.Add(new Box(8, 20, 10));
Boxes.Add(new Box(6, 10, 2));
Boxes.Add(new Box(2, 8, 4));
Boxes.Add(new Box(2, 6, 8));
Boxes.Add(new Box(4, 12, 20));
Boxes.Add(new Box(18, 10, 4));
Boxes.Add(new Box(24, 4, 18));
Boxes.Add(new Box(10, 4, 16));
Boxes.Add(new Box(10, 2, 10));
Boxes.Add(new Box(6, 18, 2));
Boxes.Add(new Box(8, 12, 4));
Boxes.Add(new Box(12, 10, 8));
Boxes.Add(new Box(14, 6, 6));
Boxes.Add(new Box(16, 6, 16));
Boxes.Add(new Box(2, 8, 12));
Boxes.Add(new Box(4, 24, 8));
Boxes.Add(new Box(8, 6, 20));
Boxes.Add(new Box(18, 18, 12));
//使用继承了Comparer<T>的比较器,进行排序。里面覆写了Compare(T a,T b)方法
Boxes.Sort(new BoxLengthFirst());
foreach (Box bx in Boxes)
{
Console.WriteLine("{0}\t{1}\t{2}",
bx.Height.ToString(), bx.Length.ToString(),
bx.Width.ToString());
}
Console.WriteLine("===============");
//获取默认比较器
Comparer<Box> defComp = Comparer<Box>.Default;
// Calling Boxes.Sort() with no parameter
// is the same as calling Boxs.Sort(defComp)
// because they are both using the default comparer.
// 等于调用Boxs.Sort(defComp);
Boxes.Sort();
foreach (Box bx in Boxes)
{
//输出高、长、宽
Console.WriteLine("{0}\t{1}\t{2}",
bx.Height.ToString(), bx.Length.ToString(),
bx.Width.ToString());
}
// This explicit interface implementation
// compares first by the length.
// Returns -1 because the length of BoxA
// is less than the length of BoxB.
BoxLengthFirst LengthFirst = new BoxLengthFirst();
Comparer<Box> bc = (Comparer<Box>)LengthFirst;
Box BoxA = new Box(2, 6, 8);
Box BoxB = new Box(10, 12, 14);
int x = LengthFirst.Compare(BoxA, BoxB);
Console.WriteLine();
Console.WriteLine(x.ToString());
Console.ReadLine();
}
}
public class BoxLengthFirst : Comparer<Box>
{
//父类抽象方法 Compare
// Compares by Length, Height, and Width.
public override int Compare(Box x, Box y)
{
if (x.Length.CompareTo(y.Length) != 0)
{
return x.Length.CompareTo(y.Length);
}
else if (x.Height.CompareTo(y.Height) != 0)
{
return x.Height.CompareTo(y.Height);
}
else if (x.Width.CompareTo(y.Width) != 0)
{
return x.Width.CompareTo(y.Width);
}
else
{
return 0;
}
}
}
// This class is not demonstrated in the Main method
// and is provided only to show how to implement
// the interface. It is recommended to derive
// from Comparer<T> instead of implementing IComparer<T>.
//没有在Main方法里演示,推荐使用继承Comparer<T>的方法。
public class BoxComp : IComparer<Box>
{
// Compares by Height, Length, and Width.
public int Compare(Box x, Box y)
{
if (x.Height.CompareTo(y.Height) != 0)
{
return x.Height.CompareTo(y.Height);
}
else if (x.Length.CompareTo(y.Length) != 0)
{
return x.Length.CompareTo(y.Length);
}
else if (x.Width.CompareTo(y.Width) != 0)
{
return x.Width.CompareTo(y.Width);
}
else
{
return 0;
}
}
}
public class Box : IComparable<Box>
{
public Box(int h, int l, int w)
{
this.Height = h;
this.Length = l;
this.Width = w;
}
public int Height { get; private set; }
public int Length { get; private set; }
public int Width { get; private set; }
public int CompareTo(Box other)
{
// Compares Height, Length, and Width.
if (this.Height.CompareTo(other.Height) != 0)
{
return this.Height.CompareTo(other.Height);
}
else if (this.Length.CompareTo(other.Length) != 0)
{
return this.Length.CompareTo(other.Length);
}
else if (this.Width.CompareTo(other.Width) != 0)
{
return this.Width.CompareTo(other.Width);
}
else
{
return 0;
}
}
}
五. Comparison<T>、 Comparer<T>、 System.IComparable、IComparable<T>的区别
Comparison<T>,继承委托。开发人员可以在外部写个用于比较大小的函数,然后作为 Comparison<T>类型的参数传入,进行比较,非常方便。
派生自 Comparer<T> 类和实现 System.IComparable 接口之间的差异如下:
若要指定默认情况下(Default获取)应如何比较两个对象,请在类中实现 System.IComparable 接口。 这可确保排序操作将使用您提供的默认比较代码。
若要定义要使用的比较器而不是默认比较器,请从 Comparer<T> 类派生。 然后,您可以在采用比较器作为参数的排序操作中使用此比较器。
- Default 属性返回的对象使用 System.IComparable<T> 泛型接口来比较两个对象。 如果类型 T 未实现 System.IComparable<T> 泛型接口,Default 属性返回使用 System.IComparable 接口的 Comparer<T>。