Próbuję dowiedzieć się, który z tych interfejsów muszę zaimplementować. Obie zasadniczo robią to samo. Kiedy użyłbym jednego nad drugim?
Odpowiedzi:
Cóż, nie są one dokładnie tym samym, co IComparer<T>
jest zaimplementowane w typie, który jest w stanie porównywać dwa różne obiekty, podczas gdy IComparable<T>
jest zaimplementowany na typach, które są w stanie porównać się z innymi wystąpieniami tego samego typu.
Zwykle używam IComparable<T>
w sytuacjach, gdy muszę wiedzieć, jak inna instancja odnosi się do this
instancji. IComparer<T>
przydaje się do sortowania kolekcji, ponieważ IComparer<T>
znajduje się poza porównaniem.
IComparable
jak jestem porównywalne . co oznacza, że można mnie porównać do czegoś innego. A IComparer
ponieważ jestem osobą porównującą, po prostu porównuję, co oznacza, że porównuję pewne rzeczy.
To zależy od jednostki. Na przykład w przypadku klasy takiej jak „Student” sensowne będzie posiadanie IComparable na podstawie nazwy.
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);
}
}
Ale jeśli nauczyciel „A” chce porównać uczniów na podstawie MathScore, a nauczyciel „B” chce porównać uczniów na podstawie EnglishScore. Dobrym pomysłem będzie oddzielne zaimplementowanie IComparer. (Bardziej jak wzorzec strategii)
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;
}
}
Wszystko zależy od tego, czy Twój typ jest zmienny, czy nie. Należy zaimplementować IComparable tylko na typach niemodyfikowalnych. Zauważ, że jeśli zaimplementujesz IComparable, musisz przesłonić Equals wraz z operatorami ==,! =, <I> (zobacz ostrzeżenie analizy kodu CA1036).
Cytując Dave'a G z tego wpisu na blogu :
Ale poprawną odpowiedzią jest zaimplementowanie IComparer zamiast IComparable, jeśli twoje obiekty są mutowalne, i przekazanie wystąpienia IComparer do funkcji sortujących, gdy jest to konieczne.
Ponieważ IComparer jest tylko jednorazowym obiektem używanym do sortowania w tym momencie, twój obiekt może mieć dowolną zmienną semantykę, którą chcesz. Co więcej, nie wymaga, ani nawet nie sugeruje używania Equals, GetHashCode ani == - możesz to zdefiniować w dowolny sposób.
Na koniec możesz zdefiniować wiele IComparer dla swojego typu w celu sortowania według różnych pól lub według różnych reguł. Jest to o wiele bardziej elastyczne niż utknięcie z jedną definicją.
W skrócie: użyj IComparable dla typów wartości i IComparer dla typów referencyjnych.
Proste wyjaśnienie poprzez opowieść
Koszykówka w liceum. To szkolny wybór dla drużyn. Chcę mieć najwyższych / najlepszych / najszybszych ludzi w moim zespole. Co ja robię?
Interfejs iComparer - porównaj dwie osoby oddzielne osoby
Compare(Fred, John)
i wypluwa, kto jest lepszy.A co z IComparable? - Porównaj się z kimś innym
Byłeś ostatnio na FB? Widzisz innych ludzi robiących fajne rzeczy: podróżowanie po świecie, tworzenie wynalazków, podczas gdy ja robię coś niezbyt fajnego - cóż, to, co robimy, to korzystanie z interfejsu IComparable.
A co z klasą porównującą?
Klasa Comparer jest abstrakcyjną klasą bazową, która implementuje interfejs IComparer. Powinieneś wywodzić się z tej klasy, aby mieć konkretną implementację. w każdym razie firma Microsoft zaleca, aby zamiast implementować interfejs IComparer, UŻYWASZ klasy Comparer:
Zalecamy wyprowadzenie z klasy Comparer zamiast implementowania interfejsu IComparer, ponieważ klasa Comparer zapewnia jawną implementację interfejsu metody IComparer.Compare i właściwość Default, która pobiera domyślną funkcję porównującą dla obiektu.
Mam nadzieję, że historie pomogą Ci zapamiętać.
Jak powiedzieli inni, nie robią tego samego.
W każdym razie, obecnie nie używam IComparer. Dlaczego miałabym? Jego odpowiedzialność (zewnętrzna jednostka używana do porównywania dwóch obiektów) może być obsługiwana znacznie lepiej za pomocą wyrażenia lambda, podobnie jak działa większość metod LINQ. Napisz szybką lambdę, która pobiera obiekty do porównania jako argumenty i zwraca wartość bool. A jeśli obiekt definiuje własną wewnętrzną operację porównania, może zamiast tego zaimplementować IComparable.
IComparable mówi, że obiekt można porównać z innym. IComparer to obiekt, który może porównać dowolne dwa elementy.
IComparer jest interfejsem używanym do sortowania tablicy, ten interfejs wymusi na klasie implementację metody Compare (T x, T y), która porówna dwa obiekty. Instancja klasy, która zaimplementowała ten interfejs, jest używana do sortowania tablicy Array.
IComparable to interfejs jest zaimplementowany w typie, który musi porównać dwa obiekty tego samego typu, Ten porównywalny interfejs wymusi na klasie implementację następującej metody CompareTo (T obj)
IEqualityComparer to interfejs, który służy do znajdowania obiektu, niezależnie od tego, czy jest równy, czy nie. Teraz zobaczymy to na przykładzie, w którym musimy znaleźć Distinct obiektu w kolekcji. Ten interfejs zaimplementuje metodę Equals (T obj1, T obj2)
Teraz bierzemy przykład, mamy klasę Employee, na podstawie tej klasy musimy stworzyć kolekcję. Teraz mamy następujące wymagania.
Sortuj tablicę za pomocą klasy Array 2. Potrzebujesz kolekcji za pomocą Linq: usuń duplikat, uporządkuj od wyższego do niższego, usuń jeden identyfikator pracownika
abstract public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { set; get; }
}
public enum SortType
{
ByID,
BySalary
}
public class EmployeeIdSorter: IComparer {public int Compare (Employee x, Employee y) {if (x.Id <y.Id) return 1; else if (x.Id> y.Id) return -1; else 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;
}
}
Więcej informacji można znaleźć poniżej http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html