IComparable Interface in C#

Last Updated : 11 Sep, 2026

IComparable is a C# interface that allows a class to define its default comparison behavior. It is useful when objects need to be arranged according to a specific ordering rule.

  • Defines the CompareTo() method for object comparison.
  • Supports ordering of custom objects based on class-defined comparison logic.
  • The generic IComparable<T> interface provides a type-safe alternative.

Example: Program to implements IComparable in a Student class. The CompareTo() method compares students using their Marks property.

C#
using System;

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

    public Student(string name, int marks)
    {
        Name = name;
        Marks = marks;
    }

    public int CompareTo(object obj)
    {
        if (obj is not Student other)
            throw new ArgumentException("Object is not a Student.");

        return Marks.CompareTo(other.Marks);
    }
}

class Program
{
    static void Main()
    {
        Student[] students =
        {
            new Student("Rahul", 85),
            new Student("Amit", 65),
            new Student("Neha", 90)
        };

        Array.Sort(students);

        foreach (Student student in students)
        {
            Console.WriteLine($"{student.Name}: {student.Marks}");
        }
    }
}

Output
Amit: 65
Rahul: 85
Neha: 90

Explanation: The Student class implements IComparable and compares objects using their Marks property. Array.Sort() calls CompareTo() to arrange the students in ascending order of marks.

Syntax

The IComparable interface belongs to the System namespace and declares the CompareTo() method.

public interface IComparable
{
int CompareTo(object? obj);
}

A class that implements IComparable must provide an implementation of CompareTo().

CompareTo() Method

CompareTo() contains the logic used to compare the current object with another object. The method receives the object being compared and returns an integer representing their ordering relationship.

Syntax

public int CompareTo(object? obj)

  • obj is the object being compared with the current object.
  • The comparison is based on the properties selected by the implementing class.
  • The returned integer determines the relative order of the two objects.

Return Values of CompareTo()

The result of CompareTo() determines the position of the current object relative to the object being compared.

Return ValueMeaning
Less than 0The current object comes before the specified object.
0The current object is equal to the specified object.
Greater than 0The current object comes after the specified object.

The exact integer value is not important; only whether the result is negative, zero, or positive matters.

Sorting Objects Using IComparable

Once a class implements IComparable, standard sorting methods can use its default comparison logic.

Array.Sort()

Array.Sort() sorts an array according to the ordering defined by CompareTo().

Array.Sort(students);

List<T>.Sort()

List<T>.Sort() can also use the default comparison implemented by the objects in the list.

List<Student> students = new List<Student>
{
new Student("Rahul", 85),
new Student("Amit", 65),
new Student("Neha", 90)
};

students.Sort();

Both methods use the comparison logic provided by IComparable to determine the order of the objects.

IComparable vs IComparable<T>

IComparable and IComparable<T> both define default comparison behavior, but the generic version provides a strongly typed comparison method.

FeatureIComparableIComparable<T>
NamespaceSystemSystem
TypeNon-genericGeneric
MethodCompareTo(object obj)CompareTo(T other)
Type safetyRequires castingType-safe
BoxingMay occur for value typesAvoids unnecessary boxing
PerformanceGenerally less efficientGenerally more efficient
Recommended for new codeLess preferredGenerally preferred

IComparable<T> Example

C#
using System;

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

    public Student(string name, int marks)
    {
        Name = name;
        Marks = marks;
    }

    public int CompareTo(Student other)
    {
        if (other == null)
            return 1;

        return Marks.CompareTo(other.Marks);
    }
}

Here, CompareTo() accepts a Student directly, so no conversion from object is required.

For new code, IComparable<T> is generally preferred because it provides type-safe comparisons and avoids the casting required by the non-generic interface.

Limitations of IComparable

Although IComparable is useful for default ordering, it is not suitable for every comparison requirement.

  • A type normally has only one default ordering defined through IComparable.
  • The non-generic interface requires working with object, which can require type checking or casting.
  • Different ordering requirements are better handled with IComparer<T>.
  • Poorly designed comparison logic can result in inconsistent sorting behavior.

Best Practices for IComparable

Follow these practices when implementing IComparable to make comparisons reliable and predictable.

  • Base the comparison on properties that clearly represent the type's default ordering.
  • Ensure comparison results are consistent for the same pair of objects.
  • Handle incompatible object types appropriately when using non-generic IComparable.
  • Prefer IComparable<T> for new implementations.
  • Keep comparison logic focused and avoid changing object state inside CompareTo().
  • Ensure the comparison behavior is consistent with equality when appropriate.
Comment

Explore