oba interfejsy wydają się porównywać obiekty pod kątem równości, więc jakie są główne różnice między nimi?
oba interfejsy wydają się porównywać obiekty pod kątem równości, więc jakie są główne różnice między nimi?
Odpowiedzi:
IEquatable<T>
dla równości.
IComparable<T>
do zamówienia.
Oprócz odpowiedzi Grega D.
Możesz zaimplementować IComparable
bez implementacji IEquatable
dla klasy, w której częściowe porządkowanie ma sens i gdzie zdecydowanie chcesz, aby konsument wywnioskował, że tylko dlatego, że CompareTo()
zwraca zero, nie oznacza to, że obiekty są równe (w celach innych niż sortowanie).
IComparable
jest tutaj całkowicie niewłaściwy. To, co masz, to bardzo szczególna kolejność, która ma zastosowanie tylko w jednej specjalnej sytuacji. W takich sytuacjach implementacja generała IComparable
jest niewłaściwa. Po to IComparer
tam są. Na przykład nie można porządkować ludzi. Ale można je sortować według wynagrodzenia, rozmiaru buta, liczby piegów lub wagi. Dlatego we IComparer
wszystkich tych przypadkach zaimplementowalibyśmy różne .
Jak podano na stronie MSDN dla IEquatable :
Interfejs IComparable definiuje
CompareTo
metodę, która określa kolejność sortowania wystąpień typu implementującego. Interfejs IEquatable definiujeEquals
metodę, która określa równość wystąpień typu implementującego.
Equals
vs. CompareTo
IComparable <T>
definiuje metodę porównania specyficzną dla typu, której można użyć do porządkowania lub sortowania obiektów.
IEquatable <T>
definiuje uogólnioną metodę, której można użyć do określenia równości.
Powiedzmy, że masz klasę Person
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person p1 = new Person() { Name = "Person 1", Age = 34 };
Person p2 = new Person() { Name = "Person 2", Age = 31 };
Person p3 = new Person() { Name = "Person 3", Age = 33 };
Person p4 = new Person() { Name = "Person 4", Age = 26 };
List<Person> people = new List<Person> { p1, p2, p3, p4 };
people.Sort();
.Ale to spowoduje wyjątek.
Framework nie wie, jak sortować te obiekty. Musisz powiedzieć, jak sortować IComparable
interfejs implementujący .
public class Person : IComparable
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(object obj)
{
Person otherPerson = obj as Person;
if (otherPerson == null)
{
throw new ArgumentNullException();
}
else
{
return Age.CompareTo(otherPerson.Age);
}
}
}
Spowoduje to prawidłowe posortowanie tablicy przy użyciu Sort()
metody method.
Equals()
metody method.var newPerson = new Person() { Name = "Person 1", Age = 34 };
var newPersonIsPerson1 = newPerson.Equals(p1);
To zwróci,false
ponieważ Equals
metoda nie wie, jak porównać dwa obiekty. Dlatego musisz zaimplementować IEquatable
interfejs i powiedzieć frameworkowi, jak wykonać porównanie. Rozszerzając poprzedni przykład, będzie wyglądać tak.
public class Person : IComparable, IEquatable<Person>
{
//Some code hidden
public bool Equals(Person other)
{
if (Age == other.Age && Name == other.Name)
{
return true;
}
else
{
return false;
}
}
}
IEquatable
używa generycznego, <Person>
a IComparable
nie?
IComparable
poprawnie implementujący . Można wymyślić sensowny przykład gdzieCompareTo(…) == 0
ma nie implikuje równość? Ja na pewno nie mogę. W rzeczywistości kontrakt interfejsu (zgodnie z MSDN) wymaga, abyCompareTo(…) == 0
implikować równość. Mówiąc wprost, w takim przypadku jak twój użyj specjalnegoComparator
przedmiotu, nie implementujIComparable
.