C# 通过实现`IComparable`和`IComparer`接口从而使用List.Sort()方法对用户类/类型进行排序

有些话、适合烂在心里 提交于 2020-02-25 19:15:03

要让List的内置Sort()方法对某个类排序,只需让这个类实现IComparable<T>接口,并增加一个CompareTo()方法。

实际上IComparable<T>接口只有CompareTo()一个方法:

以下是系统定义:

    //
    // 摘要:
    //     定义由值类型或类实现的通用比较方法,以为排序实例创建类型特定的比较方法。
    //
    // 类型参数:
    //   T:
    //     要比较的对象的类型。
    public interface IComparable<in T>
    {
        //
        // 摘要:
        //     将当前实例与同一类型的另一个对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。
        //
        // 参数:
        //   other:
        //     与此实例进行比较的对象。
        //
        // 返回结果:
        //     一个值,指示要比较的对象的相对顺序。 返回值的含义如下: 值 含义 小于零 此实例在排序顺序中位于 other 之前。 零 此实例中出现的相同位置在排序顺序中是
        //     other。 大于零 此实例在排序顺序中位于 other 之后。
        int CompareTo(T other);
    } ```

先看一个例子:

    class Human : IComparable<Human>
    {
        public int Age { get; set; }
        public int Weight { get; set; }
        public int CompareTo(Human other)
        {
            if (this.Age > other.Age)
            {
                return 1;//当前Human排在前面
            }
            else if (this.Age < other.Age)
            {
                return -1;//当前Human排在后面
            }
            else
            {
                return 0;//相同
            }
        }
    }

List.Sort()方法正是利用各个类/类型实现的CompareTo()方法循环比较实现排序的。


对于复杂的类/类型,排序方法应该是多样的,List有一个特殊的.NET Framework内置接口IComparer<T>,通过单独构件一个类来帮助List<T>对特定对象排序。

IComparer比较器接口

首先是List.Sort()方法对此重载的定义:

        //
        // 摘要:
        //     使用指定的比较器对整个 System.Collections.Generic.List`1 中的元素进行排序。
        //
        // 参数:
        //   comparer:
        //     比较元素时要使用的 System.Collections.Generic.IComparer`1 实现,若要使用默认比较器 System.Collections.Generic.Comparer`1.Default,则为
        //     null。
        //
        // 异常:
        //   T:System.InvalidOperationException:
        //     comparer 为 null,且默认比较器 System.Collections.Generic.Comparer`1.Default 找不到 System.IComparable`1
        //     泛型接口或类型为 T 的 System.IComparable 接口的实现。
        //
        //   T:System.ArgumentException:
        //     comparer 的实现导致排序时出现错误。 例如,将某个项与其自身比较时,comparer 可能不返回 0。
        public void Sort(IComparer<T> comparer); 

使用:

    class HumanComparerByWeight : IComparer<Human>
    {
        public int Compare(Human x, Human y)
        {
            if (x.Weight > y.Weight)
            {
                return 1;
            }
            else if (x.Weight < y.Weight)
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }
    }
			//Main
			//去除了其它语句
            humanList.Sort(new HumanComparerByWeight());

结合使用可以完成较为复杂的比较操作。


以下是一段完整测试程序:

  /// <summary>
    /// 按首字母进行比较排序
    /// </summary>
    class HumanComparerByName : IComparer<Human>
    {
        public int Compare(Human x, Human y)
        {
            if (x.Name[0] > y.Name[0])
            {
                return 1;
            }
            else if (x.Name[0] < y.Name[0])
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }
    }
    /// <summary>
    /// 按体重进行比较排序
    /// </summary>
    class HumanComparerByWeight : IComparer<Human>
    {
        public int Compare(Human x, Human y)
        {
            if (x.Weight > y.Weight)
            {
                return 1;
            }
            else if (x.Weight < y.Weight)
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }
    }
    class Human : IComparable<Human>
    {
        public string Name;
        public int Age { get; set; }
        public int Weight { get; set; }
        public Human(string name, int age, int weight)
        {
            this.Name = name;
            this.Age = age;
            this.Weight = weight;
        }
        public int CompareTo(Human other)
        {
            if (this.Age > other.Age)
            {
                return 1;
            }
            else if (this.Age < other.Age)
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }
        public override string ToString()
        {
            return "Name:" + this.Name + "\tAge:" + this.Age + "\tWeight:" + this.Weight;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<Human> humanList = new List<Human>
            {
                new Human("jack",33,67),
                new Human("joke",20,61),
                new Human("bob",12,78),
                new Human("tony",78,57),
                new Human("xiaoming",23,53),
                new Human("jieni",90,53),
                new Human("lily",22,50),
                new Human("peter",36,53)
            };
            Console.WriteLine("---------Sort by Age(default)---------------");
            humanList.Sort();
            foreach (var item in humanList)
            {
                Console.WriteLine(item.ToString());
            }
            Console.WriteLine("---------Sort by Weight---------------------");
            humanList.Sort(new HumanComparerByWeight());
            foreach (var item in humanList)
            {
                Console.WriteLine(item.ToString());
            }
            Console.WriteLine("---------Sort by Name-----------------------");
            humanList.Sort(new HumanComparerByName());
            foreach (var item in humanList)
            {
                Console.WriteLine(item.ToString());
            }
        }
    }

运行结果:
测试结果


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!