IComparable and IComparer in C #

 

preface

In the development process, we often encounter the problem of comparison and sorting, such as the sorting of collection arrays. The basic types provide the default comparison algorithm. For example, string provides sorting by letter, while int integer is sorted by integer size. However, in the reference type (with multiple fields), the sorting of course depends on our specific value.

IComparable interface

The interface is implemented by types whose values can be sorted or sorted, and provides strongly typed comparison methods to sort the members of generic collection objects. For example, the number can be greater than the second number, and a string can appear in alphabetical order before another string. He asked to implement a method of type definition, CompareTo(T), which indicates whether the current implementation's position in the sort order is before, after or the same as the same type and the second object. In general, methods are not invoked directly from developer code. Instead, it is called automatically by methods such as List.Sort() and Add.

Typically, the type that provides the Icomparable implementation also implements the IEquatable interface. The IEquatable interface Equals defines a method that determines the equality of instances of implementation types.

The implementation of the CompareTo(T) method must return Int32 with one of the following three values, as shown in the following table.

valuemeaning
Less than zero This object precedes the object specified by the CompareTo method in the sort order.
Fatal Frame This current instance appears in the same place in the sort order as the object specified by the CompareTo method parameter.
Greater than zero This current instance follows the object specified by the CompareTo method argument in the sort order.

Example:

    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: we sort by Age(int)

Perform test

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);
            }
        }
    }


The output is as follows

IComparer interface

The CompareTo method of IComparable interface can only sort one field at a time, so different attributes cannot be sorted. The IComparer interface provides a Compare method that compares two objects and returns a value indicating that one object is less than, equal to, or greater than the other. A class that implements the IComparer interface must provide a Compare method to Compare two objects. For example, you can create a StudentComparer class that implements IComparer and has a Compare method that compares Student objects by Name. You can then pass the StudentComparer object to the Array.Sort method, which can use the object to sort the array of Student objects.

Example

    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: we sort by Name(string)

Perform test

    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);
            }
        }
    }

The output results are as follows

IComparable and IComparer

In the above example, we have boxed and unpacked objects for many times. At this time, we can change the method to generic. The emergence of generic also allows us to avoid the waste of resources in boxing and unpacking

Finally, the code fragment we implemented is as follows:

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);
           
        }
    }

summary

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

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

 

 

turn   https://www.cnblogs.com/yyfh/p/12129000.html

Keywords: C#

Added by steveclondon on Fri, 29 Oct 2021 04:14:29 +0300