web-dev-qa-db-fra.com

différence entre IComparable et IComparer

Quelle est la différence entre les interfaces IComparable et IComparer? Est-il nécessaire d'utiliser cette interface toujours avec la méthode Array.Sort()

43
Raghav55

Comme son nom le suggère, IComparable<T> lit je suis comparable. IComparable<T> lorsque défini pour T vous permet de comparer la instance actuelle avec une autre instance du même type. IComparer<T> lit je compare, je compare. IComparer<T> est utilisé pour comparer deux instances quelconques de T, généralement en dehors de la portée des instances de T.

Quant à à quoi ils servent peut être déroutant au début. D'après la définition, il devrait être clair qu'ainsi IComparable<T> (défini dans la classe T elle-même) devrait être le standard de facto pour fournir la logique de tri. La valeur par défaut Sort sur List<T> etc s'appuie sur cela. L'implémentation de IComparer<T> sur T n'aide pas le tri régulier. Par la suite, implémenter IComparable<T> sur une classe autre que T a peu de valeur. Ce:

class MyClass : IComparable<T>

fait rarement sens.

D'autre part 

class T : IComparable<T>
{
    public int CompareTo(T other)
    {
        //....
    }
}

voici comment cela devrait être fait.

IComparer<T> peut être utile lorsque vous souhaitez effectuer un tri en fonction d'un ordre personnalisé, mais pas en règle générale. Par exemple, dans une classe de Person, vous aurez peut-être besoin de Trier les personnes en fonction de leur âge. Dans ce cas, vous pouvez faire:

class Person
{
    public int Age;
}

class AgeComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return x.Age - y.Age;
    }
}

Maintenant, AgeComparer aide à trier une liste basée sur Age

var people = new Person[] { new Person { age = 23 }, new Person(){ age = 22 } };
people.Sort(p, new AgeComparer()); //person with age 22 comes first now.

De même, IComparer<T> sur T n'a pas de sens. 

class Person : IComparer<Person>

C'est vrai que cela fonctionne, mais n'a pas fière allure et défait la logique. 

Généralement, vous avez besoin de IComparable<T>. Aussi, idéalement, vous ne pouvez avoir qu'un seul IComparable<T> alors que plusieurs IComparer<T> sont possibles en fonction de différents critères.

Le IComparer<T> et le IComparable<T> sont exactement analogues aux IEqualityComparer<T> et IEquatable<T> qui servent à tester l’égalité plutôt qu’à comparer/trier; un bon fil ici où j'ai écrit exactement la même réponse :)

82
nawfal
  • IComparable - Définit une interface pour un objet avec une méthode CompareTo () qui prend un autre objet du même type et compare l'objet actuel à l'objet transmis. Il internalise la comparaison avec l'objet, ce qui permet une opération de comparaison plus en ligne. Il est utile lorsqu'il n'y a qu'un seul moyen logique, ou un moyen extrêmement commun par défaut, de comparer des objets d'un type.
  • IComparer - Définit une interface avec une méthode Compare () qui prend deux objets d'un autre type (qui n'ont pas à implémenter IComparable) et les compare. Ceci externalise la comparaison et est utile lorsqu'il existe de nombreuses manières possibles de comparer deux objets d'un type, ou lorsque le type n'implémente pas IComparable (ou si l'implémentation IComparable compare une manière différente de celle que vous voulez) et avoir le contrôle sur la source de ce type.
34
KeithS

La meilleure explication que j'ai lue est "L'objet à trier implémentera IComparable tandis que la classe qui va trier les objets implémentera IComparer." ( la source )

Si les objets que vous essayez de trier n'implémentent pas IComparable, vous devez créer une classe qui implémente IComparer (et accepte ces types d'objet à des fins de comparaison) et le transmet à la méthode Array.Sort ().

13
Ken Pespisa

IComparable est utilisé pour fournir un ordre de tri par défaut pour vos objets.

IComparer doit fournir des mécanismes de comparaison supplémentaires.

voir cet article pour référence. http://support.Microsoft.com/kb/320727

6
niknowj

IComparer compare deux objets qui lui sont donnés. IComparable est implémenté par l'objet qui est comparé, dans le but de comparer avec un autre de lui-même.

C'est une bonne idée d'implémenter IComparable pour le tri des objets. IComparable peut être utile pour trier selon différents critères (par exemple, le tri par un champ sélectionnable dans l'objet).

Voir aussi: Quand utiliser IComparable <T> Vs. IComparer <T>

1
Sean Edwards

Les objets qui sont des instances de classes qui implémentent IComparable peuvent être comparés à d'autres objets. (Lisez IComparable comme "je peux être comparé.") La méthode sur cette interface qui fait cela est CompareTo. Ceci est utile si vous voulez que les instances de telles classes sachent se comparer à d'autres objets.

Les objets qui sont des instances de classes qui implémentent IComparer peuvent être utilisés pour comparer des paires d'objets. (Lisez IComparer comme "je peux comparer.") La méthode utilisée pour cette interface est Compare. Ceci est utile si vous souhaitez découpler la logique de comparaison de la classe d'objets comparés. Un cas où vous pouvez utiliser ceci si vous avez différentes façons de comparer des objets (comparaisons de chaînes sensibles à la casse ou sensibles à la casse).

0
jason