C#中的List.Sort()--集合排序⽅法全⾯解析
在C#中,List.Sort() 不仅为我们提供了默认的排序⽅法,还为我们提供了4种⾃定义排序的⽅法,通过默认排序⽅法,我们⽆需重写任何Sort()⽅法的实现代码,就能对单参数类型的List数据进⾏单⼀规则的排序,如果通过对这些⽅法进⾏改进我们可以轻松做到对多参数、多规则的复杂排序。
下⾯是C#⾃定义排序的4种⽅法:
List<T>.Sort();
List<T>.Sort(IComparer<T> Comparer);
List<T>.Sort(int index, int count, IComparer<T> Comparer);
List<T>.Sort(Comparison<T> comparison);
实现⽬标
假设存在⼀个People类,包含Name、Age属性,在客户端中创建List保存多个实例,希望对List中的内容根据Name和Age参数进⾏排序,排序规则为,先按姓名升序排序,如果姓名相同再按年龄的升序排序:
class People
{
public People(string name, int age) { Name = name; Age = age; }
public string Name { get; set; } //姓名
public int Age { get; set; } //年龄
}
// 客户端
class Client
{
static void Main(string[] args)
{
List<People> peopleList = new List<People>();
peopleList.Add(new People("张三", 22));
peopleList.Add(new People("张三", 24));
peopleList.Add(new People("李四", 18));
peopleList.Add(new People("王五", 16));
peopleList.Add(new People("王五", 30));
}
}
⽅法⼀、对People类继承IComparable接⼝,实现CompareTo()⽅法
该⽅法为系统默认的⽅法,单⼀参数时会默认进⾏升序排序。但遇到多参数(Name、Age)排序时,我们需要对该默认⽅法进⾏修改。
⽅法⼀:People类继承IComparable接⼝,实现CompareTo()⽅法
IComparable<T>:定义由值类型或类实现的通⽤⽐较⽅法,旨在创建特定于类型的⽐较⽅法以对实例进⾏排序。
原理:⾃⾏实现的CompareTo()⽅法会在list.Sort()内部进⾏元素两两⽐较,最终实现排序
class People : IComparable<People>
{
public People(string name, int age) { Name = name;Age = age; }
public string Name { get; set; }
public int Age { get; set; }
// list.Sort()时会根据该CompareTo()进⾏⾃定义⽐较
public int CompareTo(People other)
{
if (this.Name != other.Name)
{
return this.Name.CompareTo(other.Name);
}
else if (this.Age != other.Age)
{
return this.Age.CompareTo(other.Age);
}
else return 0;
}
// 客户端
peopleList.Sort();
/
/ OUTPUT:
//  李四 18
//  王五 16
//  王五 30
//  张三 22
//  张三 24
⽅法⼆:增加People类的外部⽐较类,继承IComparer接⼝、实现Compare()⽅法
区别于上述继承IComparable的⽅法,该⽅法不可在People内继承实现IComparer接⼝,⽽是需要新建⽐较⽅法类进⾏接⼝实现
⽅法⼆:新建PeopleComparer类、继承IComparer接⼝、实现Compare()⽅法
原理:list.Sort()将PeopleComparer类的实例作为参数,在内部使⽤Compare()⽅法进⾏两两⽐较,最终实现排序(注:上述⽅法为CompareTo(),此处为Compare()⽅法)
// ⾃定义⽐较⽅法类
class PeopleComparer : IComparer<People>
{
// 区别于CompareTo()单参数,此处为双参数
public int Compare(People x, People y)
{
if (x.Name != y.Name)
{
return x.Name.CompareTo(y.Name);
}
else if (x.Age != y.Age)
{
return x.Age.CompareTo(y.Age);
}
else return 0;
}
}
// 客户端
// 传⼊参数为⾃定义⽐较类的实例
peopleList.Sort(new PeopleComparer());
// OUTPUT:
//  李四 18
/
/  王五 16
//  王五 30
//  张三 22
//  张三 24
同理,List<T>.Sort(int index, int count, IComparer<T> Comparer) ⽅法的参数:待排元素起始索引、待排元素个数、排序⽅法
⽅法三、采⽤泛型委托 Comparison<T>,绑定⾃定义的⽐较⽅法
区别于上述继承接⼝的⽅法,此⽅法的参数为泛型委托 Comparison<T>
委托原型:public delegate int Comparison<in T>(T x, T y);
⽅法三:依照委托的使⽤⽅法,⾸先创建委托实例MyComparison,并绑定到⾃定义的⽐较⽅法PeopleComparison()上,最终调⽤list.Sort()时将委托实例传⼊
原理:list.Sort()根据传⼊的委托⽅法,进⾏两两元素⽐较最终实现排序
// 客户端
class Client
{
// ⽅法0 ⾃定义⽐较⽅法
public static int PeopleComparison(People p1, People p2)
{
if (p1.Name != p2.Name)
{
return p1.Name.CompareTo(p2.Name);
else if (p1.Age != p2.Age)
{
return p1.Age.CompareTo(p2.Age);
}
else return 0;
}
static void Main(string[] args)
{
/ 创建list ... /
// ⽅法0 创建委托实例并绑定
Comparison<People> MyComparison = PeopleComparison;
// 传⼊该实例实现⽐较⽅法
peopleList.Sort(MyComparison);
/
/ OUTPUT:
//  李四 18
//  王五 16
//  王五 30
//  张三 22
//  张三 24
}
}
此外,既然Comparison<T>是泛型委托,则完全可以⽤ Lambda表达式进⾏描述:
// Lambda表达式实现Comparison委托
peopleList.Sort((p1, p2) =>
{
if (p1.Name != p2.Name)
{
return p2.Name.CompareTo(p1.Name);
}
else if (p1.Age != p2.Age)
{
return p2.Age.CompareTo(p1.Age);
}
else return 0;
});
/
/ OUTPUT:
//  张三 24
//  张三 22
//  王五 30
//  王五 16
//  李四 18
总结
虽然本⽂仅使⽤了List<T>⼀种容器对Sort()⽅法进⾏阐述,但是不同容器的使⽤Sort()的⽅法⼤相径庭,因为核⼼的原理都是应⽤两种接⼝及泛型委托:
两种接⼝:IComparable<T> 、 IComparer<T>
泛型委托:Comparison<T>
参考
附:⼀个完整的测试Demo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ListSort
{
class Program
{
static void DisplayInfo<T>(List<T> list) {
//输出List元素内容
System.Console.Write("{0} ",item.ToString());
}
System.Console.WriteLine("");
}
// ⽅法3 ⾃定义委托泛型⽐较⽅法
public static int PeopleComparison(People p1, People p2)
{
if (p1.Name != p2.Name)
{
return p1.Name.CompareTo(p2.Name);
}
else if (p1.Age != p2.Age)
{
return p1.Age.CompareTo(p2.Age);
}
else return 0;
}
static void Main(string[] args)
{
List<People> peopleList = new List<People>();
peopleList.Add(new People("张三", 22));
peopleList.Add(new People("张三", 24));
peopleList.Add(new People("李四", 18));
peopleList.Add(new People("王五", 16));
peopleList.Add(new People("王五", 30));
System.Console.WriteLine("排序前原始数据:");
DisplayInfo(peopleList);
System.Console.WriteLine("------------------------------------");
System.Console.WriteLine("⽅法1排序后数据:");
peopleList.Sort();
DisplayInfo(peopleList);
System.Console.WriteLine("⽅法2排序后数据:");
DisplayInfo(peopleList);
/
/ ⽅法1 使⽤IComparer<T>接⼝。
peopleList.Sort(new PeopleComparer());
// ⽅法2 除以上两种⽅法以外还可以使⽤另⼀种⽅法,在People类中实现IComparable<T>  peopleList.Sort();
System.Console.WriteLine("⽅法3排序后数据:");
DisplayInfo(peopleList);
// ⽅法3 创建泛型委托实例并绑定
Comparison<People> MyComparison = PeopleComparison;
// 传⼊该实例实现⽐较⽅法
peopleList.Sort(MyComparison);
System.Console.WriteLine("⽅法3排序后数据:");
DisplayInfo(peopleList);
// ⽅法3 使⽤Comparison<T>委托,Lambda写法
peopleList.Sort((left, right) =>
{
//先按姓名排序,如果姓名相同再按年龄排序
int x = left.Name.CompareTo(right.Name);
if(x==0) {
if (left.Age > right.Age)
x = 1;
else if (left.Age == right.Age)
x = 0;
else
writeline方法属于类x = -1;
}
return x;
});
}
}
  //⽅法⼀
public class People : IComparable<People>
public int Age { get;set;}
public string Name { get;set;}
public People(string name,int age) {
this.Name = name;
this.Age = age;
}
public override string ToString() {
string result = "";
result = "["+this.Name+","+ this.Age.ToString()+"]";
return result;
}
public int CompareTo(People other)
{
int x = this.Name.CompareTo(other.Name);
if(x==0) {
if (this.Age > other.Age)
x = 1;
else if (this.Age == other.Age)
x = 0;
else
x = -1;
}
return x;
}
}
/
/⽅法⼆
public class PeopleComparer : IComparer<People>
{
public int Compare(People left, People right)
{
int x = left.Name.CompareTo(right.Name);
if(x==0) {
if (left.Age > right.Age)
x = 1;
else if (left.Age == right.Age)
x = 0;
else
x = -1;
}
return x;
}
}
}
补充:C# IComparable和IComparer接⼝和⾃定义⽐较器
前⾔
ArrayList⾥⾯有⼀个⽅法:
public virtual void Sort(IComparer comparer);
使⽤指定的⽐较器对整个 System.Collections.ArrayList 中的元素进⾏排序。
comparer:⽐较元素时要使⽤的 System.Collections.IComparer 实现。
啥玩意啊?
正⽂
1.Comparer类简单介绍
想弄清楚这个,我们先来看看这么⼀个类。
在System.Collections名称空间中,有这么⼀个类:Comparer。顾名思义,他可以实现对简单类型的⽐较,什么意思呢?来看如下代码:
int a=1,b=2;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。