разница между IComparable и IComparer

В чем разница между интерфейсами IComparable и IComparer? Нужно ли всегда использовать этот интерфейс с методом Array.Sort()


person Raghav55    schedule 12.05.2011    source источник
comment
Вы проверяли документация?   -  person Cody Gray    schedule 12.05.2011
comment
IComparable — это объект, который можно сравнить без использования IComparer. Простой простой. ;)   -  person jalf    schedule 12.05.2011


Ответы (6)


Как следует из названия, IComparable<T> означает Я сравним. IComparable<T> при определении для T позволяет сравнить текущий экземпляр с другим экземпляром того же типа. IComparer<T> читает Я сравниваю, я сравниваю. IComparer<T> используется для сравнения любых двух экземпляров T, обычно вне области действия экземпляров T.

Что касается для чего они нужны, поначалу может возникнуть путаница. Из определения должно быть ясно, что, следовательно, IComparable<T> (определенный в самом классе T) должен быть стандартом де-факто для обеспечения логики сортировки. На этом основано значение по умолчанию Sort на List<T> и т. д. Реализация IComparer<T> на T не помогает обычной сортировке. Следовательно, реализация IComparable<T> в любом другом классе, кроме T, имеет мало смысла. Этот:

class MyClass : IComparable<T>

редко имеет смысл.

С другой стороны

class T : IComparable<T>
{
    public int CompareTo(T other)
    {
        //....
    }
}

как это должно быть сделано.

IComparer<T> может быть полезен, когда вам требуется сортировка на основе пользовательского порядка, но не в качестве общего правила. Например, в классе Person в какой-то момент вам может потребоваться Сортировать людей по возрасту. В этом случае вы можете сделать:

class Person
{
    public int Age;
}

class AgeComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return x.Age - y.Age;
    }
}

Теперь AgeComparer помогает сортировать список на основе Age.

var people = new Person[] { new Person { age = 23 }, new Person(){ age = 22 } };
people.Sort(p, new AgeComparer()); //person with age 22 comes first now.

Точно так же IComparer<T> на T не имеет смысла.

class Person : IComparer<Person>

Правда это работает, но выглядит не очень хорошо и нарушает логику.

Обычно вам нужно IComparable<T>. Также в идеале у вас может быть только один IComparable<T>, тогда как несколько IComparer<T> возможны на основе разных критериев.

IComparer<T> и IComparable<T> в точности аналогичны IEqualityComparer<T> и IEquatable<T>, которые используются для проверки равенства, а не для сравнения/сортировки; хороший поток здесь, где я написал точно такой же ответ: )

person nawfal    schedule 06.12.2012
comment
Спасибо за ваш ответ. у меня вопрос: класс MyClass : IComparable‹T› редко имеет смысл. Почему бы и нет - что в этом плохого? - person BKSpurgeon; 05.02.2016
comment
@BKSpurgeon, потому что IComparable<T> предназначен для обеспечения порядка по умолчанию для экземпляров T. Мало того, что это имеет смысл из самого названия IComparable, это то, что очевидно из определения метода CompareTo на IComparables. Определение public int CompareTo(T), так что вы можете сделать jon.CompareTo(mark), jon & mark, будучи, конечно, людьми. Когда вы пишете class RandomClass : IComparable<SomethingElse>, ur CompareTo, сделайте код похожим на refrigerator.CompareTo(parrot). Хотя технически вам может где-то это понадобиться, в мире .NET это не так. - person nawfal; 05.02.2016
comment
@BKSpurgeon Это может сбить с толку разработчиков .NET, поскольку это не норма. В тех случаях, когда вам это нужно, вы можете просто иметь статический метод (может быть методом расширения) в соответствующем классе, который говорит public int Compare(Refrigerator r, Parrot p) - person nawfal; 05.02.2016
comment
Не думаю, что это сработает -people.Sort(p, new AgeComparer()); вместо этого Array.Sort(люди, новый AgeComparer()) - person ni3.net; 29.05.2016

  • IComparable — определяет интерфейс для объекта с помощью метода CompareTo(), который берет другой объект того же типа и сравнивает текущий объект с переданным. Он интернализует сравнение с объектом, обеспечивая более встроенную операцию сравнения, и полезен, когда есть только один логический способ или чрезвычайно распространенный способ по умолчанию для сравнения объектов определенного типа.
  • IComparer — определяет интерфейс с методом Compare(), который берет два объекта другого типа (которые не должны реализовывать IComparable) и сравнивает их. Это выносит сравнение наружу и полезно, когда есть много возможных способов сравнить два объекта типа или когда тип не реализует IComparable (или реализация IComparable сравнивает не так, как вы хотите), и вы не иметь контроль над источником этого типа.
person KeithS    schedule 12.05.2011
comment
См. статью журнала Visual Studio Magazine Многоуровневая сортировка с IComparable и IComparer для подробных примеров. - person lauxjpn; 09.12.2019

Лучшее объяснение, которое я читал, таково: «Объект для сортировки будет реализовывать IComparable, а класс, который будет сортировать объекты, будет реализовывать IComparer». (источник)

Если объекты, которые вы пытаетесь отсортировать, не реализуют IComparer, вам нужно создать класс, реализующий IComparer (и принимающий эти типы объектов для сравнения), и передать его методу Array.Sort().

person Ken Pespisa    schedule 12.05.2011

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

IComparer предоставляет дополнительные механизмы сравнения.

см. эту статью для справки. http://support.microsoft.com/kb/320727

person niknowj    schedule 20.10.2011

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

Рекомендуется реализовать IComparable для сортировки объектов. IComparable может быть полезен для сортировки по разным критериям (например, сортировка по выбираемому полю в объекте).

Также см.: Когда использовать IComparable‹T› Vs. IComparer‹T›

person Sean Edwards    schedule 12.05.2011

Объекты, являющиеся экземплярами классов, реализующих IComparable, можно сравнивать с другими объектами. (Прочитайте IComparable как «Меня можно сравнить».) В этом интерфейсе это делает метод CompareTo. Это полезно, если вы хотите, чтобы экземпляры таких классов знали, как сравнивать себя с другими объектами.

Объекты, являющиеся экземплярами классов, реализующих IComparer, можно использовать для сравнения пар объектов. (Прочитайте IComparer как "Я могу сравнить".) Метод этого интерфейса, который делает это, называется Compare. Это полезно, если вы хотите отделить логику сравнения от класса сравниваемых объектов. Один из случаев, когда вы можете использовать это, если у вас есть различные способы сравнения объектов (это сравнение строк без учета регистра и с учетом регистра).

person jason    schedule 12.05.2011