Когда использовать IComparable <T> Vs. IComparer <Т>

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

Это зависит от объекта. Например, для класса, такого как "Student", имеет смысл иметь IComparable на основе Name.

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);  
    }
}

Но если учитель "A" хочет сравнить студентов на основе MathScore, а учитель "B" хочет сравнить студентов на основе 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;
    }
}

Ответ 4

Все зависит от того, изменен ли ваш тип или нет. Вы должны только внедрять IComparable в непеременные типы. Обратите внимание: если вы реализуете IComparable, вы должны переопределить Equals вместе с ==,! =, < и > (см. Предупреждение анализа кода CA1036).

Цитата Dave G из это сообщение в блоге:

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

Поскольку IComparer - всего лишь одноразовый объект, используемый для сортировки в этот момент времени, ваш объект может иметь любую изменчивую семантику, которую вы желаете. Кроме того, он не требует или даже не предлагает использовать Equals, GetHashCode или == - вы можете определить его каким-либо образом.

Наконец, вы можете определить несколько IComparer для вашего типа для сортировки по разным полям или с разными правилами. Это гораздо более гибко, чем застревание с одним определением.

Короче: Используйте IComparable для типов значений и IComparer для ссылочных типов.

Ответ 5

Простое объяснение с помощью истории

баскетбол средней школы. это выбор школьного двора для команд. Я хочу получить самых высоких/лучших/быстрых людей в моей команде. Что мне делать?

Интерфейс Icomparer. Сравните двух людей с отдельными людьми.

  • Это позволяет мне сравнивать любых двух парней, выстроенных в линию......... что в основном это. Фред против Джона.......... я бросаю их в конкретный класс, который реализует интерфейс. Compare(Fred, John) и он выплевывает, кто лучше.

Как насчет IComparable? - Сравните себя с кем-то другим

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

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

Как насчет класса Comparer?

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

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

Резюме

  • IComparer - выровняйте две вещи и сравните.
  • IComparable - сравните себя с другими на FB.

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

IEqualityComparer - это интерфейс, который используется для поиска объекта, независимо от того, является он равным или нет. Теперь мы увидим это в примере, где нам нужно найти отличительный элемент объекта в коллекции. Этот интерфейс реализует метод Равны (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 Сравнить (Employee x, Employee y)           {               если (x.Id < y.Id)                   return 1;               else if (x.Id > y.Id)                   return -1;               еще                   return 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