103 votes

Quand utiliser IComparable<T> Vs. IComparer<T>

Je suis à essayer de comprendre lequel de ces interfaces j'ai besoin de mettre en œuvre. Ils font essentiellement la même chose. Quand devrais-je utiliser l'un plutôt que l'autre?

99voto

Andrew Hare Points 159332

Eh bien, ils ne sont pas tout à fait la même chose que IComparer<T> est mis en œuvre sur un type qui est capable de comparer deux objets différents, tout IComparable<T> est mis en œuvre sur les types qui sont en mesure de se comparer avec d'autres instances du même type.

J'ai tendance à utiliser IComparable<T> pour les moments où j'ai besoin de savoir comment un autre exemple se rapporte à l' this de l'instance. IComparer<T> est utile pour le tri des collections de l' IComparer<T> se tient à l'extérieur de la comparaison.

43voto

yfeldblum Points 42613

Utiliser IComparable<T> lorsque la classe a une valeur intrinsèque de la comparaison.

Utiliser IComparer<T> lorsque vous voulez une méthode de comparaison autre que la classe intrinsèque de comparaison, si elle en a un.

29voto

Ajay Bhosale Points 550

Il dépend de l'entité. Par exemple pour une classe comme "Étudiant", il est logique d'avoir IComparable basé sur le Nom.

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

Mais si un enseignant " A "veut comparer des étudiants en s'appuyant sur MathScore, et professeur" B " veut comparer des étudiants en s'appuyant sur EnglishScore. Il sera une bonne idée de mettre en place IComparer séparément. (En plus comme un modèle de stratégie)

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

10voto

Mr. Bungle Points 562

Tout dépend si c'est votre type est mutable ou pas. Vous devez seulement mettre en œuvre IComparable sur la non-mutable types. Notez que si vous mettez en œuvre IComparable, vous devez remplacer égal à Égal, avec ==, !=, opérateurs < et > (voir l'Analyse du Code d'avertissement CA1036).

Citant Dave G de ce blog:

Mais la bonne réponse est de mettre en œuvre IComparer au lieu de IComparable si vos objets sont mutables, et de passer une instance de l'interface IComparer à des fonctions de tri si nécessaire.

Depuis l'interface IComparer est tout simplement un jetable objet utilisé pour le tri à ce point dans le temps, votre objet peut avoir tout mutable sémantique que vous désirez. En outre, il ne nécessite ni même de suggérer à l'aide d'égal à Égal, GetHashCode, ou == - vous êtes libre de le définir de la manière que vous s'il vous plaît.

Enfin, vous pouvez définir plusieurs IComparer pour votre type de tri sur des domaines différents ou avec des règles différentes. C'est beaucoup plus souple que d'être coincé avec une définition.

En bref: l'Utilisation IComparable pour les types de valeur et IComparer pour les types référence.

4voto

jalf Points 142628

Comme d'autres l'ont dit, ils ne font pas la même chose.

Dans tous les cas, ces jours-ci, j'ai tendance à ne pas utiliser IComparer. Pourquoi serais-je? Sa responsabilité (une entité externe utilisé pour comparer deux objets) peuvent être traitées beaucoup plus propre avec une expression lambda, semblable à la façon dont la plupart de LINQ méthodes de travail. Écrire un petit lambda qui prend les objets à comparer comme arguments, et renvoie un booléen. Et si l'objet définit ses propres intrinsèque de l'opération de comparaison, il peut mettre en œuvre IComparable à la place.

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