Відповіді:
Ну, це не зовсім те саме, що IComparer<T>
реалізовано для типу, який здатний порівнювати два різні об'єкти, а IComparable<T>
реалізується на типах, які здатні порівнювати себе з іншими екземплярами того ж типу.
Я схильний використовувати IComparable<T>
час, коли мені потрібно знати, як інший екземпляр стосується this
екземпляра. IComparer<T>
є корисним для сортування колекцій у вигляді IComparer<T>
стендів поза порівнянням.
IComparable
як я порівняний . це означає, що мене можна порівняти з чимось іншим. І читайте, IComparer
як я порівняльник, я просто порівнюю, що означає, що я порівнюю деякі речі.
Це залежить від сутності. Наприклад, для наступного класу, як "Студент", має сенс мати ICпорівнянний на основі Імені.
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;
}
}
Все залежить від того, мінливий ваш тип чи ні. Ви повинні тільки реалізувати IComparable на які не змінюються типів. Зауважте, що якщо ви реалізуєте IComparable, ви повинні перекрити рівність разом з операторами ==,! =, <І> (див. Попередження про аналіз коду CA1036).
Цитуючи Дейва Г з цієї публікації в блозі :
Але правильна відповідь полягає в тому, щоб застосувати IComparer замість IComparable, якщо ваші об'єкти є змінними, і передайте екземпляр IComparer для функцій сортування, коли це необхідно.
Оскільки IComparer - це просто одноразовий об'єкт, який використовується для сортування в цей момент часу, ваш об’єкт може мати будь-яку змінну семантику, яку ви бажаєте. Крім того, він не вимагає або навіть пропонує використовувати Equals, GetHashCode або == - ви можете визначити це будь-яким способом, яким ви хочете.
Нарешті, ви можете визначити кілька типів IComparer для вашого типу для сортування в різних полях або з різними правилами. Це набагато гнучкіше, ніж дотримуватися одного визначення.
Коротше кажучи: Використовуйте IComparable для типів значень та IComparer для еталонних типів.
Просте пояснення через розповідь
Баскетбол середньої школи Це шкільний двір для команд. Я хочу отримати найвищих / найкращих / найшвидших людей у своїй команді. Що мені робити?
Інтерфейс IComparer - Порівняйте двох людей, роздільних людей
Compare(Fred, John)
і це випльовує, хто кращий.Що з IComparable? - Порівняйте себе з кимось іншим
Ви нещодавно були на ФБ? Ви бачите інших людей, які роблять класні речі: подорожують світом, створюють винаходи, в той час як я роблю щось не зовсім круте - ну, що ми робимо, це використовувати інтерфейс IComparable.
А як щодо класу порівняння?
Клас Порівняння - це абстрактний базовий клас, який реалізує інтерфейс IComparer. Ви повинні випливати з цього класу, щоб мати конкретну реалізацію. у будь-якому випадку, Microsoft рекомендує вам використовувати клас Порівняння, а не реалізовувати інтерфейс IComparer:
Ми рекомендуємо виходити з класу Порівняння замість реалізації інтерфейсу IComparer, оскільки клас Порівняння забезпечує явну реалізацію інтерфейсу методу IComparer.Compare та властивості за замовчуванням, що отримує порівняння за замовчуванням для об'єкта.
Сподіваюся, історії допоможуть вам запам'ятати.
Як говорили інші, вони не роблять те саме.
У будь-якому випадку, в ці дні я, як правило, не користуюся 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
}
публічний клас EmployeeIdSorter: IComparer {public int Порівняти (Employee x, Employee y) {if (x.Id <y.Id) return 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