C# 中的IComparable和IComparer

前言

在开发过程当中常常会遇到比较排序的问题,好比说对集合数组的排序等状况,基本类型都提供了默认的比较算法,如string提供了按字母进行排序,而int整数则是根据整数大小进行排序.可是在引用类型中(具备多个字段),那么这个排序固然也是取决于咱们特定的值。git

IComparable接口

该接口由其值能够排序或排序的类型实现,并提供强类型的比较方法以对泛型集合对象的成员进行排序,例如数字能够大于第二个数字,一个字符串能够在另外一个字符串以前以字母顺序出现。他要求实现类型定义的一个方法,CompareTo(T)该方法指示当前实如今排序顺序中的位置是在同一个类型和第二个对象以前、以后仍是与其相同。一般,不会直接从开发人员代码中调用方法。相反他由List .Sort()和Add等方法自动调用。 github

一般,提供Icomparable 实现的类型还IEquatable 实现接口。IEquatable 接口Equals定义方法,该方法肯定实现类型的实例的相等性。 算法

CompareTo(T)方法的实现必须Int32返回具备如下三个值之一的,以下表所示。api

含义
小于零 此对象在排序顺序中位于CompareTo方法所指定的对象以前。
此当前实例在排序顺序中与CompareTo方法参数指定的对象出如今同一位置。
大于零 此当前实例位于排序顺序中由CompareTo方法自变量指定的对象以后。

示例:数组

class Student : IComparable
    {
        public string Name { get; set; }

        public int Age { get; set; }
        public int CompareTo(object obj)
        {
            if (!(obj is Student))
            {
                throw new ArgumentException("Compared Object is not of student");
            }
            Student student = obj as Student;
            return Age.CompareTo(student.Age);
        }
    }

Ps:咱们根据经过Age(int)来进行咱们的排序测试

执行测试code

class Program
    {
        static void Main(string[] args)
        {
            ArrayList studentList = new ArrayList {
                new Student{Name="a",Age=9 },
                  new Student{Name="a3",Age=7 },
                 new Student{Name="a1",Age=6 },
                 new Student{Name="a2",Age=10 },
            };
            studentList.Sort();
            StudentComparable(studentList);

            Console.ReadLine();
        }

        private static void StudentComparable(ArrayList studentList)
        {
            foreach (Student item in studentList)
            {
                Console.WriteLine("Name:{0},Age:{1}", item.Name, item.Age);
            }
        }
    }

输出以下对象

IComparer接口

IComparable 接口的CompareTo方法一次只能对一个字段进行排序,所以没法对不一样的属性进行排序。IComparer接口提供了Compare方法,该方法比较两个对象并返回一个值,该值指示一个对象小于,等于或大于另外一个对象。实现IComparer接口的类必须提供比较两个对象的Compare方法。例如,您能够建立一个StudentComparer类,该类实现IComparer,并具备一个Compare方法,该方法按Name比较Student对象。而后,您能够将StudentComparer对象传递给Array.Sort方法,它能够使用该对象对Student对象的数组进行排序。blog

示例排序

class StudentComparer : IComparer
    {

        public int Compare(object x, object y)
        {
            Student x1 = x as Student;
            Student y1 = y as Student;
            return x1.Name.CompareTo(y1.Name);
        }
    }

Ps:咱们根据Name(string)进行排序

执行测试

class Program
    {
        static void Main(string[] args)
        {
            ArrayList studentList = new ArrayList {
                new Student{Name="a",Age=9 },
                  new Student{Name="a3",Age=7 },
                 new Student{Name="a1",Age=6 },
                 new Student{Name="a2",Age=10 },
            };
            studentList.Sort(new StudentComparer());
            StudentComparable(studentList);

            Console.ReadLine();
        }

        private static void StudentComparable(ArrayList studentList)
        {
            foreach (Student item in studentList)
            {
                Console.WriteLine("Name:{0},Age:{1}", item.Name, item.Age);
            }
        }
    }

输出结果以下

IComparable 和IComparer

上述示例中咱们将对象进行了屡次的装箱和拆箱,那么此时咱们能够将方法改成泛型的,泛型的出现也让咱们避免了装箱和拆箱的资源浪费.

最终咱们实现的代码片断以下:

IComparable

class Student : IComparable<Student>
    {
        public string Name { get; set; }

        public int Age { get; set; }

        public int CompareTo([AllowNull] Student other)
        {
            return Age.CompareTo(other.Age);
        }
    }

IComparer

class StudentComparer : IComparer<Student>
    {

        public int Compare([AllowNull] Student x, [AllowNull] Student y)
        {
            return x.Name.CompareTo(y.Name);
           
        }
    }

总结

参考:https://docs.microsoft.com/en-us/dotnet/api/system.icomparable-1?view=netframework-4.8

示例:https://github.com/hueifeng/BlogSample/tree/master/src/CompareDemo

相关文章
相关标签/搜索