В чем разница между интерфейсами IComparable
и IComparer
? Нужно ли всегда использовать этот интерфейс с методом Array.Sort()
разница между IComparable и IComparer
Ответы (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>
, которые используются для проверки равенства, а не для сравнения/сортировки; хороший поток здесь, где я написал точно такой же ответ: )
IComparable<T>
предназначен для обеспечения порядка по умолчанию для экземпляров T
. Мало того, что это имеет смысл из самого названия IComparable
, это то, что очевидно из определения метода CompareTo
на IComparable
s. Определение public int CompareTo(T)
, так что вы можете сделать jon.CompareTo(mark)
, jon & mark, будучи, конечно, людьми. Когда вы пишете class RandomClass : IComparable<SomethingElse>
, ur CompareTo
, сделайте код похожим на refrigerator.CompareTo(parrot)
. Хотя технически вам может где-то это понадобиться, в мире .NET это не так.
- person nawfal; 05.02.2016
public int Compare(Refrigerator r, Parrot p)
- person nawfal; 05.02.2016
- IComparable — определяет интерфейс для объекта с помощью метода CompareTo(), который берет другой объект того же типа и сравнивает текущий объект с переданным. Он интернализует сравнение с объектом, обеспечивая более встроенную операцию сравнения, и полезен, когда есть только один логический способ или чрезвычайно распространенный способ по умолчанию для сравнения объектов определенного типа.
- IComparer — определяет интерфейс с методом Compare(), который берет два объекта другого типа (которые не должны реализовывать IComparable) и сравнивает их. Это выносит сравнение наружу и полезно, когда есть много возможных способов сравнить два объекта типа или когда тип не реализует IComparable (или реализация IComparable сравнивает не так, как вы хотите), и вы не иметь контроль над источником этого типа.
Лучшее объяснение, которое я читал, таково: «Объект для сортировки будет реализовывать IComparable, а класс, который будет сортировать объекты, будет реализовывать IComparer». (источник)
Если объекты, которые вы пытаетесь отсортировать, не реализуют IComparer, вам нужно создать класс, реализующий IComparer (и принимающий эти типы объектов для сравнения), и передать его методу Array.Sort().
IComparable используется для предоставления порядка сортировки по умолчанию для ваших объектов.
IComparer предоставляет дополнительные механизмы сравнения.
см. эту статью для справки. http://support.microsoft.com/kb/320727
IComparer сравнивает два переданных ему объекта. IComparable реализуется сравниваемым объектом с целью сравнения с другим объектом.
Рекомендуется реализовать IComparable для сортировки объектов. IComparable может быть полезен для сортировки по разным критериям (например, сортировка по выбираемому полю в объекте).
Также см.: Когда использовать IComparable‹T› Vs. IComparer‹T›
Объекты, являющиеся экземплярами классов, реализующих IComparable
, можно сравнивать с другими объектами. (Прочитайте IComparable
как «Меня можно сравнить».) В этом интерфейсе это делает метод CompareTo
. Это полезно, если вы хотите, чтобы экземпляры таких классов знали, как сравнивать себя с другими объектами.
Объекты, являющиеся экземплярами классов, реализующих IComparer
, можно использовать для сравнения пар объектов. (Прочитайте IComparer
как "Я могу сравнить".) Метод этого интерфейса, который делает это, называется Compare
. Это полезно, если вы хотите отделить логику сравнения от класса сравниваемых объектов. Один из случаев, когда вы можете использовать это, если у вас есть различные способы сравнения объектов (это сравнение строк без учета регистра и с учетом регистра).