Я пытаюсь понять, какой из этих интерфейсов мне нужно реализовать. По сути, они оба делают одно и то же. Когда я буду использовать одно вместо другого?
Ответы:
Ну, это не совсем то же самое, что IComparer<T>
реализовано в типе, способном сравнивать два разных объекта, в то время IComparable<T>
как реализовано в типах, которые могут сравнивать себя с другими экземплярами того же типа.
Я обычно использую, IComparable<T>
когда мне нужно знать, как другой экземпляр относится к this
экземпляру. IComparer<T>
полезен для сортировки коллекций, поскольку IComparer<T>
стоит вне сравнения.
IComparable
что я сравним . а значит, меня можно сравнить с чем-то другим. И читая, IComparer
как я сравниваю, я просто сравниваю, что означает, что я сравниваю некоторые вещи.
Это зависит от сущности. Например, следуя примеру класса «Студент», имеет смысл иметь IComparable на основе имени.
class Student : IComparable
{
public string Name { get; set; }
public int MathScore { get; set; }
public int EnglishScore { get; set; }
public int TotalScore
{
get
{
return this.MathScore + this.EnglishScore;
}
}
public int CompareTo(object obj)
{
return CompareTo(obj as Student);
}
public int CompareTo(Student other)
{
if (other == null)
{
return 1;
}
return this.Name.CompareTo(other.Name);
}
}
Но если учитель «А» хочет сравнить учеников на основе MathScore, а учитель «Б» хочет сравнить учеников на основе EnglishScore. Было бы неплохо реализовать IComparer отдельно. (Больше похоже на шаблон стратегии)
class CompareByMathScore : IComparer<Student>
{
public int Compare(Student x, Student y)
{
if (x.MathScore > y.MathScore)
return 1;
if (x.MathScore < y.MathScore)
return -1;
else
return 0;
}
}
Все зависит от того, является ли ваш тип изменчивым или нет. Вы должны реализовывать IComparable только для неизменяемых типов. Обратите внимание, что если вы реализуете IComparable, вы должны переопределить Equals вместе с операторами ==,! =, <И> (см. Предупреждение анализа кода CA1036).
Цитата Дэйва Джи из этого сообщения в блоге :
Но правильный ответ - реализовать IComparer вместо IComparable, если ваши объекты изменчивы, и при необходимости передать экземпляр IComparer функциям сортировки.
Поскольку IComparer - это просто одноразовый объект, используемый для сортировки в этот момент времени, ваш объект может иметь любую изменяемую семантику, которую вы пожелаете. Кроме того, он не требует и даже не предлагает использовать Equals, GetHashCode или == - вы можете определять его как угодно.
Наконец, вы можете определить несколько IComparer для своего типа для сортировки по разным полям или с разными правилами. Это гораздо более гибко, чем зацикливаться на одном определении.
Вкратце: используйте IComparable для типов значений и IComparer для ссылочных типов.
Простое объяснение через рассказ
Баскетбол средней школы. Это выбор школьного двора для команд. Я хочу собрать в команду самых высоких / лучших / самых быстрых людей. Что мне делать?
Интерфейс IComparer - Сравните двух людей разных людей
Compare(Fred, John)
и выплевывает, кто лучше.А как насчет IComparable? - Сравните себя с кем-то другим
Вы недавно были на FB? Вы видите, как другие люди занимаются крутыми вещами: путешествуют по миру, создают изобретения, а я делаю что-то не такое уж крутое - ну, мы используем интерфейс IComparable.
А как насчет класса Comparer?
Класс Comparer - это абстрактный базовый класс, реализующий интерфейс IComparer. Чтобы иметь конкретную реализацию, вы должны быть производным от этого класса. в любом случае Microsoft рекомендует ДЕЙСТВИТЕЛЬНО использовать класс Comparer, а не реализовывать интерфейс IComparer:
Мы рекомендуем унаследовать от класса Comparer вместо реализации интерфейса IComparer, потому что класс Comparer предоставляет явную реализацию интерфейса метода IComparer.Compare и свойства Default, которое получает компаратор по умолчанию для объекта.
Надеюсь, рассказы помогут вам вспомнить.
Как говорили другие, они не делают то же самое.
В любом случае сейчас я не использую IComparer. Зачем мне? Его ответственность (внешняя сущность, используемая для сравнения двух объектов) может быть решена гораздо более четко с помощью лямбда-выражения, аналогично тому, как работает большинство методов LINQ. Напишите короткую лямбду, которая принимает объекты для сравнения в качестве аргументов и возвращает логическое значение. И если объект определяет свою собственную внутреннюю операцию сравнения, вместо этого он может реализовать IComparable.
IComparable говорит, что объект можно сравнивать с другим. IComparer - это объект, который может сравнивать любые два элемента.
IComparer - это интерфейс, который используется для сортировки массива, этот интерфейс заставит класс реализовать метод Compare (T x, T y), который будет сравнивать два объекта. Экземпляр класса, который реализовал этот интерфейс, используется при сортировке массива.
IComparable - это интерфейс, реализованный в типе, который должен сравнивать два объекта одного типа. Этот сопоставимый интерфейс заставит класс реализовать следующий метод CompareTo (T obj)
IEqualityComparer - это интерфейс, который используется для поиска объекта, независимо от того, равен он или нет. Теперь мы увидим это в примере, где нам нужно найти Отличительные черты объекта в коллекции. Этот интерфейс реализует метод Equals (T obj1, T obj2)
Теперь мы возьмем пример, у нас есть класс Employee, на основе этого класса мы должны создать коллекцию. Теперь у нас есть следующие требования.
Отсортируйте массив с помощью класса Array 2. Нужна коллекция с помощью Linq: удалить дубликат, упорядочить по возрастанию к меньшему, удалить один идентификатор сотрудника
abstract public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { set; get; }
}
public enum SortType
{
ByID,
BySalary
}
открытый класс EmployeeIdSorter: IComparer {public int Compare (Employee x, Employee y) {if (x.Id <y.Id) return 1; иначе, если (x.Id> y.Id) return -1; иначе вернуть 0; }}
public class EmployeeSalarySorter : IComparer<Employee>
{
public int Compare(Employee x, Employee y)
{
if (x.Salary < y.Salary)
return 1;
else if (x.Salary > y.Salary)
return -1;
else
return 0;
}
}
Для получения дополнительной информации см. Ниже http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html