102 votes

Quelle est la différence entre les interfaces IComparable et IEquatable ?

Les deux interfaces semblent comparer les objets pour l'égalité, alors quelles sont les principales différences entre elles ?

196voto

Greg D Points 24218

IEquatable teste si deux objets sont égaux.

IComparable impose un ordre total aux objets comparés.

Par exemple, IEquatable vous dirait que 5 n'est pas égal à 7. IComparable vous dirait que 5 vient avant 7.

21voto

Islam Yahiatene Points 632

IEquatable<T> pour l'égalité.

IComparable<T> pour les commandes.

12voto

Damien_The_Unbeliever Points 102139

En plus de la réponse de Greg D :

Vous pourriez mettre en œuvre IComparable sans mettre en œuvre IEquatable pour une classe où un ordre partiel a du sens, et où vous voulez vraiment que le consommateur déduise que juste parce que CompareTo() retourne zéro, cette no impliquent que les objets sont égaux (à des fins autres que le tri).

11 votes

Cela ressemble beaucoup plus à un comparateur de cas spéciaux qu'à un objet implémentant. IComparable correctement. Pouvez-vous trouver un exemple significatif où CompareTo(…) == 0 fait no implique l'égalité ? Certainement pas. En fait, le contrat d'interface (selon MSDN) nécessite que CompareTo(…) == 0 implique l'égalité. Pour dire les choses crûment, dans un cas comme le vôtre, utilisez une méthode spéciale Comparator l'objet, faites no mettre en œuvre IComparable .

2 votes

@Konrad - J'ai indiqué plusieurs mises en garde : le type n'implémente pas IEquatable (il est donc évident que le créateur ne souhaite pas inclure un test d'égalité), et les résultats de CompareTo sont utilisés pour le tri, no pour évaluer l'égalité. Il faut aussi se demander quelle égalité est pertinente (référence, valeur, en ignorant les attributs "arbitraires" - un livre bleu de 500 pages peut être "égal" à un livre rouge de 500 pages, pour les besoins de IComparable).

4 votes

Votre dernière phrase est fausse, et c'est l'erreur particulière que je voulais souligner : IComparable est tout à fait inapproprié ici. Ce que vous avez, c'est un très particulier qui ne s'applique que dans une situation particulière. Pour de telles situations, l'implémentation d'un ordre général IComparable a tort. C'est ce que IComparer sont là pour ça. Par exemple, les personnes ne peuvent pas être ordonnées de manière significative. Mais ils peut être classés en fonction de leur salaire, de leur pointure, du nombre de leurs taches de rousseur ou de leur poids. Par conséquent, nous mettrons en place différents IComparer pour tous ces cas.

7voto

Will Eddins Points 6451

Comme indiqué sur le Page MSDN pour IEquatable :

L'interface IComparable définit le site CompareTo qui détermine l'ordre de tri des instances du type type d'implémentation. La méthode IEquatable définit l'interface Equals méthode, qui détermine l'égalité des instances du type d'implémentation.

Equals vs. CompareTo

6voto

Nips Points 772

IComparable <T> définit une méthode de comparaison spécifique à un type qui peut être utilisée pour ordonner ou trier des objets.

IEquatable <T> définit une méthode généralisée qui peut être utilisée pour mettre en œuvre la détermination de l'égalité.


Disons que vous avez la classe Personne

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

Pour trier ces objets, vous pouvez utiliser people.Sort(); .

Mais cela déclenchera une exception.

enter image description here

Le cadre ne sait pas comment trier ces objets. Vous devez lui dire comment trier en implémentant IComparable interface.

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

Cela permettra de trier le tableau correctement avec Sort() méthode.


Ensuite, pour comparer deux objets, vous pouvez utiliser Equals() méthode.

var newPerson = new Person() { Name = "Person 1", Age = 34 };
var newPersonIsPerson1 = newPerson.Equals(p1);

Cela donnera false parce que Equals ne sait pas comment comparer deux objets. Vous devez donc implémenter IEquatable et indiquer au framework comment effectuer la comparaison. Dans le prolongement de l'exemple précédent, cela ressemblera à ceci.

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

1 votes

Merci pour cette excellente explication. Question : pourquoi IEquatable utiliser un générique <Person> y IComparable ne le fait pas ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X