Разница между IComparable и IComparer в C#

IComparable и IComparer используются для сравнения объектов, но отличаются способом реализации и областью применения.

IComparable

Интерфейс IComparable<T> реализуется в классе, который должен поддерживать естественный порядок сортировки. В нём определяется метод CompareTo, который сравнивает текущий объект с другим.

Пример реализации IComparable<T>:

using System;
using System.Collections.Generic;

class Person : IComparable<Person>
{
    public string Name { get; }
    public int Age { get; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public int CompareTo(Person other)
    {
        return Age.CompareTo(other.Age);
    }
}

class Program
{
    static void Main()
    {
        List<Person> people = new()
        {
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        };
        
        people.Sort();
        
        foreach (var person in people)
        {
            Console.WriteLine($"{person.Name}, {person.Age}");
        }
    }
}

В этом примере объекты Person сортируются по возрасту, так как метод CompareTo использует Age для сравнения.

IComparer

IComparer<T> используется, если требуется несколько способов сортировки. Он позволяет создать отдельный класс-компаратор с методом Compare.

Пример реализации IComparer<T>:

using System;
using System.Collections.Generic;

class Person
{
    public string Name { get; }
    public int Age { get; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

class NameComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return string.Compare(x.Name, y.Name, StringComparison.Ordinal);
    }
}

class Program
{
    static void Main()
    {
        List<Person> people = new()
        {
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        };
        
        people.Sort(new NameComparer());
        
        foreach (var person in people)
        {
            Console.WriteLine($"{person.Name}, {person.Age}");
        }
    }
}

В этом случае объекты Person сортируются по имени, так как используется компаратор NameComparer.

Различия между IComparable и IComparer

ОсобенностьIComparableIComparer
Где реализуетсяВ самом классеВ отдельном классе
Какой порядок сортировкиОдин встроенныйМожно создавать несколько вариантов
Используется приСтандартной сортировкеРазных способах сравнения

Когда использовать

  • IComparable<T> – если у объекта есть естественный порядок сортировки.
  • IComparer<T> – если требуется несколько вариантов сортировки или если нельзя изменить класс объекта.

Оба интерфейса помогают управлять сортировкой объектов, но IComparer<T> даёт больше гибкости, позволяя использовать разные алгоритмы сравнения.