我们通常使用泛型集合来存放数据,常见的如:List 、Dictionary等。在使用这些泛型集合时我们有时需要对其进行排序,一般用到的是继承IComparer<T>接口,实现int IComparer<T>.Compare(T t1, T t2)方法。下面介绍c#中list排序的实现方法

一、初始数据

假设我们有一个Student对象,简单起见这个对象只有三个属性,分别是学好、姓名、年龄。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericCompare
{
    class Student
    {
        public Student()
        {
        }
        public Student(string no, string name, int age)
        {
            this.No = no;
            this.Name = name;
            this.Age = age;
        }
        public string No
        {
            get;
            set;
        }
        public string Name
        {
            get;
            set;
        }
        public int Age
        {
            get;
            set;
        }
    }
}

插入如下数据

			   
List<Student> students = new List<Student>();

students.Add(new Student("001","kenshincui",25));

students.Add(new Student("002", "miaoer", 23));

students.Add(new Student("003", "shenjinjuan", 22));

students.Add(new Student("004", "nieyanxin", 24));
   

二、调用默认的sort()会报错

报错信息

20140728225306316

报错原因

从图中的提示我们可以看出错误原因是由于进行比较的对象并未有任何一个实现IComparable接口,因此也就无法完成排序。事实上对于无参Sort()方法是使用Comparer.Default比较器来排序的,而此比较器进行比较时首先就会检查T是否实现了IComparable泛型接口,如果实现了则使用该实现。否则将坚持是否实现了IComparable接口。如果均未实现则引发InvalidOperationException异常。也就是说如果想使用此方法需要实现ICompara泛型接口或者IComparable接口

三、list常用排序方法

1、List.Sort (泛型 Comparison) 法

此方法的参数是Comparison类型,其实是一个包含两个参数的委托,因此使用此方法,我们只需要定义一个委托,其两个参数均为Student类型,在委托实现的方法比较两个Student对象的Age属性即可。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericCompare
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student("001","kenshincui",25));
            students.Add(new Student("002", "miaoer", 23));
            students.Add(new Student("003", "shenjinjuan", 22));
            students.Add(new Student("004", "nieyanxin", 24));
            Console.WriteLine("未进行排序之前:");
            foreach (Student st in students)
            {
                Console.WriteLine(st.No+","+st.Name+","+st.Age+";");
            }
            Console.WriteLine("List.Sort (泛型 Comparison) 排序之后:");
            students.Sort(delegate(Student a, Student b) { return a.Age.CompareTo(b.Age); });
            foreach (Student st in students)
            {
                Console.WriteLine(st.No + "," + st.Name + "," + st.Age + ";");
            }
            Console.ReadKey();
        }
    }
}

运行结果

20140728225748706

2、List.Sort (泛型 IComparer)

此方法需要一个泛型IComparer接口类型,因此只要定义一个类实现此接口然后再调用此方法即可。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericCompare
{
    class StudentCompare :IComparer<Student>
    {
        public int Compare(Student a, Student b)
        {
            return a.Age.CompareTo(b.Age);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericCompare
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student("001","kenshincui",25));
            students.Add(new Student("002", "miaoer", 23));
            students.Add(new Student("003", "shenjinjuan", 22));
            students.Add(new Student("004", "nieyanxin", 24));
            Console.WriteLine("未进行排序之前:");
            foreach (Student st in students)
            {
                Console.WriteLine(st.No+","+st.Name+","+st.Age+";");
            }
            Console.WriteLine("List.Sort (泛型 IComparer) 排序之后:");
            students.Sort(new StudentCompare());
            foreach (Student st in students)
            {
                Console.WriteLine(st.No + "," + st.Name + "," + st.Age + ";");
            }
            Console.ReadKey();
        }
    }
}

四、设定排序范围

虽然上面的方法都实现了泛型集合排序,但是有时我们并不需要对整个集合进行排序而是指对其中一定范围内容的对象进行排序,那么我们就需要使用Sort方法的第四种重载:

List.Sort (Int32, Int32, 泛型 IComparer)

前两个参数分别代表排序的其实位置和排序长度,最后一个参数仍然是泛型IComparer接口类型。上面我们已经定义了StudentComparer类,实现了IComparer接口,这里就可以直接使用了,下面我们只对前三个学生按照年龄由小到大进行排序。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericCompare
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student("001","kenshincui",25));
            students.Add(new Student("002", "miaoer", 23));
            students.Add(new Student("003", "shenjinjuan", 22));
            students.Add(new Student("004", "nieyanxin", 24));
            Console.WriteLine("未进行排序之前:");
            foreach (Student st in students)
            {
                Console.WriteLine(st.No+","+st.Name+","+st.Age+";");
            }
            Console.WriteLine("List.Sort (Int32, Int32, 泛型 IComparer) 排序之后:");
            students.Sort(0, 3, new StudentCompare());
            foreach (Student st in students)
            {
                Console.WriteLine(st.No + "," + st.Name + "," + st.Age + ";");
            }
            Console.ReadKey();
        }
    }
}

运行效果

20140728230253363

如果觉得我的文章对你有用,请随意赞赏