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?
Réponses
Trop de publicités?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.
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;
}
}
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.
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.