ambas as interfaces parecem comparar objetos por igualdade, então quais são as principais diferenças entre elas?
ambas as interfaces parecem comparar objetos por igualdade, então quais são as principais diferenças entre elas?
Respostas:
IEquatable<T>
para a igualdade.
IComparable<T>
para fazer o pedido.
Além da resposta de Greg D:
Você pode implementar IComparable
sem implementar IEquatable
para uma classe em que uma ordem parcial faça sentido e onde você definitivamente deseja que o consumidor deduza que, só porque CompareTo()
retorna zero, isso não significa que os objetos são iguais (para qualquer coisa diferente de fins de classificação).
IComparable
é totalmente inapropriado aqui. O que você tem é uma ordem muito particular que se aplica apenas a uma situação especial. Para tais situações, implementar um general IComparable
é errado. É para isso que IComparer
existem. Por exemplo, as pessoas não podem ser ordenadas de forma significativa. Mas podem ser encomendados de acordo com o salário, o tamanho do sapato, a quantidade de sardas ou o peso. Portanto, implementaríamos IComparer
s diferentes para todos esses casos.
Conforme declarado na Página do MSDN para IEquatable :
A interface IComparable define o
CompareTo
método, que determina a ordem de classificação das instâncias do tipo de implementação. A interface IEquatable define oEquals
método, que determina a igualdade das instâncias do tipo de implementação.
Equals
vs. CompareTo
IComparable <T>
define um método de comparação específico de tipo que pode ser usado para ordenar ou classificar objetos.
IEquatable <T>
define um método generalizado que pode ser usado para implementar para determinar a igualdade.
Digamos que você tenha uma classe 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();
.Mas isso lançará uma exceção.
O Framework não sabe como classificar esses objetos. Você precisa dizer como classificar a IComparable
interface de implementação .
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);
}
}
}
Isso classificará a matriz corretamente com o Sort()
método.
Equals()
método.var newPerson = new Person() { Name = "Person 1", Age = 34 };
var newPersonIsPerson1 = newPerson.Equals(p1);
Isso retornaráfalse
porque o Equals
método não sabe como comparar dois objetos. Portanto, você precisa implementar a IEquatable
interface e dizer ao framework como fazer a comparação. Estendendo o exemplo anterior, ficará assim.
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
usa um genérico <Person>
e IComparable
não?
IComparable
corretamente. Você pode dar um exemplo significativo emCompareTo(…) == 0
que não implique igualdade? Certamente não posso. Na verdade, o contrato de interface (conforme MSDN) exige queCompareTo(…) == 0
implique igualdade. Para ser franco, em um caso como o seu, use umComparator
objeto especial , não implementeIComparable
.