Вопрос

Я пытаюсь выяснить, какой из этих интерфейсов мне нужно реализовать.Они оба, по сути, делают одно и то же.Когда я буду использовать один вместо другого?

Это было полезно?

Решение

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

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

Другие советы

Использовать IComparable<T> когда класс имеет внутреннее сравнение.

Использовать IComparer<T> когда вам нужен метод сравнения, отличный от внутреннего сравнения класса, если он есть.

Это зависит от сущности.Например, для такого класса, как «Студент», имеет смысл использовать 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? - Сравните себя с кем-то другим

Вы недавно были на ФБ?Вы видите, как другие люди делают классные вещи:Путешествуя по миру, создавая изобретения, пока я делаю что-то не столь крутое - мы используем интерфейс IComparable.

  • Мы сравниваем текущий экземпляр (вас) с другим объектом (кем-то другим) того же типа (человеком).

А как насчет класса сравнения?

Класс Comparer — это абстрактный базовый класс, реализующий интерфейс IComparer.Чтобы получить конкретную реализацию, вам следует получить наследие от этого класса.в любом случае Microsoft рекомендует использовать класс Comparer, а не реализовывать интерфейс IComparer:

Мы рекомендуем создавать производные от класса Comparer вместо реализации интерфейса IComparer, поскольку класс Comparer предоставляет явную реализацию интерфейса метода IComparer.Compare и свойства Default, которое получает компаратор по умолчанию для объекта.

Краткое содержание

  • IComparer — соедините две вещи и сравните.
  • IComparable - сравните себя с другими на ФБ.

Надеюсь, эти истории помогут вам вспомнить.

Как говорили другие, они не делают то же самое.

В любом случае, сейчас я склонен не использовать IComparer.Зачем мне?Его ответственность (внешняя сущность, используемая для сравнения двух объектов) можно гораздо проще реализовать с помощью лямбда-выражения, аналогично тому, как работает большинство методов LINQ.Напишите быструю лямбду, которая принимает объекты для сравнения в качестве аргументов и возвращает логическое значение.А если объект определяет собственную внутреннюю операцию сравнения, вместо этого он может реализовать IComparable.

IComparable говорит, что объект можно сравнивать с другим.IComparer — это объект, который может сравнивать любые два элемента.

IComparer - это интерфейс, который используется для сортировки массива, этот интерфейс заставит класс реализовать Сравнить (T x,T y) метод, который будет сравнивать два объекта.Экземпляр класса, реализовавшего этот интерфейс, используется при сортировке массива.

IComparable — это интерфейс, реализованный в типе, который необходимо сравнивать два объекта одного и того же типа. Этот сопоставимый интерфейс заставит класс реализовать следующий метод CompareTo(T obj)

IEqualityComparer — это интерфейс, который используется для поиска объекта, независимо от того, равен он или нет. Теперь мы увидим это в примере, где нам нужно найти отличие объекта в коллекции.Этот интерфейс реализует метод Равные (T obj1, T obj2)

Теперь возьмем пример: у нас есть класс «Сотрудник», на основе этого класса нам нужно создать коллекцию.Теперь у нас есть следующие требования.

Сортировка массива с помощью класса 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
}

общедоступный классСотрудникIdSorter:IComparer { public int Compare(Employee x, Employee y) { if (x.Id < y.Id) возврат 1;в противном случае, если (x.Id > y.Id) возврат -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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top