#c_sharp
Что лучше использовать для сортировки IComparer или IComparable?Можете сказать что из них лучше использовать и почему? Лично я сам не совсем понял что из них лучше.
Ответы
Ответ 1
В .NET классов коллекций и массивы поддерживают сортировку,с помощью одного метода, который, как правило, называется Sort().Однако метод Sort() по умолчанию работает только для наборов примитивных типов, как int или string. Для сортировки наборов сложных объектов применяется интерфейс IComparable: public interface IComparable { int CompareTo(object o); } Метод CompareTo на выходе возвращает целое число, которое может иметь одно из трех значений: Меньше нуля. Значит, текущий объект должен находиться перед объектом, который передается в качестве параметра Равен нулю. Значит, оба объекта равны Больше нуля. Значит, текущий объект должен находиться после объекта, передаваемого в качестве параметр IComparable имеет обобщенную версию IComparable. IComparable , если определено для T, позволяет сравнить текущий экземпляр с другим экземпляром того же типа. IComparable сопоставим,а IComparer сравнитель. Кроме интерфейса IComparable платформа .NET также предоставляет интерфейс IComparer: interface IComparer { int Compare(object o1, object o2); } Метод Compare предназначен для сравнения двух объектов o1 и o2. Он также возвращает три значения, в зависимости от результата сравнения: Если первый объект больше второго, то возвращается число больше 0 если меньше - то число меньше нуля если оба объекта равны, возвращается ноль IComparer имеет обобщенную версию IComparer . IComparer может быть полезна,когда вам требуется сортировка на основе пользовательского порядка,но не как общее правило.Например,в классе Person в какой-то момент вам может потребоваться сортировка людей в зависимости от их возраста. В этом случае вы можете public class Person { public int Age; } public class AgeComparer : IComparer { public int Compare(Person x, Person y) { return x.Age - y.Age; } } Обычно вам нужно IComparable .В идеале вы можете иметь только один IComparable , тогда как несколько IComparer возможны на основе разных критериев. Ответ 2
Это зависит от того, какой реальный смысл ваших данных. Если ваша структура данных имеет естественную операцию сравнения, то вы должны реализовать IComparable(причин использовать нетипизированный IComparable практически нет), при этом сортировка будет работать как надо. Например, для структуры данных Rational, представляющей собой натуральную дробь, операция сравнения очевидна: class Rational : IComparable { public int Numerator { get; } public int Denominator { get; } public int CompareTo(Rational that) { var result = Math.Sign((this.Numerator * that.Denominator) .CompareTo(this.Denominator * that.Numerator)); if (Math.Sign(this.Denominator) != Math.Sign(that.Denominator)) result = -result; return result; } } Тогда смысл сортировки понятен: вы сортируете ваши объекты в их естественном порядке. Если же у ваших объектов нету естественного порядка, то вам нет смысла реализовывать IComparable . Например, если у вас есть объект Human, у него нет естественного порядка. Иногда вам может захотеться отсортировать коллекцию людей иногда по росту, иногда по фамилии, иногда по дате рождения. В этом случае для сортировки вы либо указываете, как вычислить «вес» каждого объекта (как в LINQ-шном OrderBy), либо указываете, как сравнить два элемента (класс IComparer или просто лямбда-функция Comparison ). Легче всего, наверное, через OrderBy: humans.OrderBy(h => h.Surname).ToList() Чуть сложнее через Comparison : humans.Sort((p, q) => { var n1 = p.Surname; var n2 = q.Surname; return (n1 > n2) ? 1 : (n1 < b2) ? -1 : 0; }); или просто humans.Sort((p, q) => p.Surname.CompareTo(q.Surname)); То же можно сделать и через реализацию интерфейса IComparer : class SurnameComparer : IComparer { public int Compare(Human p, Human q) { return p.Surname.CompareTo(q.Surname); } } var cmp = new SurnameComparer; humans.Sort(cmp); — но этот путь обычно самый длинный, и нужен не так часто: например, когда вам нужно повторное использование этого «сравнивателя». Ответ 3
Это два разных варианта одного и того же процесса. Интерфейс IComparable, позволяет объекту быть "сравниваемым" с другим, что позволяет методом сортировки сортировать коллекции объектов, не вдумываясь что это за объекты. Т.е. объект сам знает, какой у него "статус" к другим объектам. Например есть объект Email с полем email и Name с полем name, и есть единый список из Email и Name. Email сравнивает email.toString() и o.toString() а Name соответсвенно с name. В итоге, если есть ситуация отсортировать этот общий список, он сортируется правильно, в соответствии с сущностью объектов. Интерфейс IComparer позволяет реализовать собственный вариант сортировки, для конкретного случая, учитывая конкретную ситуацию, а не суть классов. Например, можно реализовать на базе этого интерфейса два варианта ByNameComparer и ByEmailComparer. И применить их в зависимости от ситуации, к одной коллекции - в одном случай по имени, в другом - по емейлу.
Комментариев нет:
Отправить комментарий