List<T>类可以使用Sort()方法对元素排序。Sort()方法使用快速排序算法,比较所有的元素,直到整个列表排好序为止。
Sort()方法使用了几个重载的方法。可以传递给它的参数由泛型委托Comparison<T>和泛型接口IComparer<T>以及一个范围值和泛型接口IComparer<T>。
public void List<T>.Sort();
public void List<T>.Sort(Comparison<T>);
public void List<T>.Sort(IComparer<T>);
public void List<T>.Sort(Int32,Int32,IComparer<T>);
只有集合中的元素实现了IComparable接口,才能使用不带参数的Sort()方法。
自定义类Racer实现了IComparable<T>接口,可以按姓氏对赛车手排序:
racers.Sort();
如果需要按照元素类型不默认支持的方式排序,就应使用其他技术,例如,传递一个实现了IComparer<T>接口的对象。
RacerComparer类为Racer类型实现了接口IComparer<T>。这个类允许按名字、姓氏、国籍或获胜次数排序。排序的种类用内部枚举类型CompareType定义。CompareType枚举类型用RacerComparer类的构造函数设置。ICompaer<Racer>接口定义了排序所需的Compare()方法。在这个方法的实现代码中,使用了string和int类型的CompareTo()方法:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
namespace 列表排序
{
class Program
{
static void Main(string[] args)
{
var racer = new Racer(3,"Jenny","Henry","Japan",34);
var racer2 = new Racer(2,"Code","Winders","China",12);
var racer3 = new Racer(1,"Visual","Studio","Ameraca",9);
List<Racer> racers = new List<Racer> {
racer,
racer2,
racer3
};
System.Console.WriteLine("Sort by FirstName");
//现在,可以对RacerCompare类的一个实例使用Sort()方法。传递枚举RacerCompare.CompareType.Country,
//按属性FirstName对集合排序。
racers.Sort(new RacerComparer(RacerComparer.ComapareType.FirstName));
foreach(var value in racers){
System.Console.WriteLine(value);
}
System.Console.WriteLine();
System.Console.WriteLine("Sort by Wins");
racers.Sort(new RacerComparer(RacerComparer.ComapareType.Wins));
foreach(var value in racers){
System.Console.WriteLine(value);
}
}
}
public class Racer{
public int Id{get;}
public string FirstName{get;}
public string LastName{get;}
public string Country{get;}
public int Wins{get;}
public Racer(int id,string firstName,string lastName,string country,int wins){
Id = id;
FirstName = firstName;
LastName = lastName;
Country = country;
Wins = wins;
}
public override string ToString()=>$"{Id} {FirstName} {LastName} {Country} {Wins}";
}
public class RacerComparer: IComparer<Racer>{
public enum ComapareType{
FirstName,
LastName,
Country,
Wins
}
private ComapareType _compareType;
public RacerComparer(ComapareType comapareType)=>_compareType = comapareType;
public int Compare(Racer x,Racer y){
if(x == null && x == null) return 0;
if(x == null) return -1;
if(y == null) return 1;
int result;
switch(_compareType){
case ComapareType.FirstName:
return string.Compare(x.FirstName,y.FirstName);
case ComapareType.LastName:
return string.Compare(x.LastName,y.LastName);
case ComapareType.Country:
result = string.Compare(x.Country,y.Country);
if(result == 0)
return string.Compare(x.LastName,y.LastName);
else
return result;
case ComapareType.Wins:
return x.Wins.CompareTo(y.Wins);
default:
throw new ArgumentException("Invalid Compare Type");
//注:如果传递给Compare方法的两个元素的顺序相同,该方法则返回0.如果返回值小于0,
//说明第一个参数小于第二个参数;
//如果返回值大于0,则第一个参数大于第二个参数。
//传递null作为参数,Compare方法并不会抛出一个NullReferenceException异常。
//相反,因为null的位置在其他任何元素之前,所以如果第一个参数为null,该方法返回-1,
//如果第二个参数为null,则返回+1。
}
}
}
}
排序的另一种方式是使用重载的Sort()方法,该方法需要一个Comparison<T>委托:
public void List<T>.Sort(Comparison<T>);
Comparison<T>是一个方法的委托,该方法由两个T类型的参数,返回类型为int。如果参数值相等,该方法就必须返回0.如果第一个参数比第二个参数小,它就必须返回一个小于0的值;否则,必须返回一个大于0的值。
public delegate int Comparison<T>(T x,T y);
现在可以把一个lambda表达式传递给Sort()方法,按获胜次数排序。两个参数的类型是Racer,在其实现代码中,使用int类型的CompareTo()方法比较Wins属性。在实现代码中,因为使用逆序使用r2和r1,所以获胜次数以降序方式排序。调用方法之后,完整的赛车手列表就按赛车手的获胜次数排序。也可以调用Reverse()方法,逆转整个集合的顺序。
System.Console.WriteLine("Sort by Wins");
//racers.Sort(new RacerComparer(RacerComparer.ComapareType.Wins));
racers.Sort((r1,r2)=>r2.Wins.CompareTo(r1.Wins));
foreach(var value in racers){
System.Console.WriteLine(value);
}
System.Console.WriteLine("Use reverse");
racers.Reverse();
foreach(var value in racers){
System.Console.WriteLine(value);
}