IComparable
ne fonctionne que dans un sens
Disons que vous avez une Employee
classe. Dans une vue, vous voulez tout afficher Employees
trié par nom - dans une autre, par adresse. Comment allez-vous y parvenir? Pas avec IComparable
, du moins pas de façon idiomatique.
IComparable
a la logique au mauvais endroit
L'interface est utilisée en appelant .Sort()
. Dans une vue montrant Customer
trié par nom, aucun code n'implique comment il va être trié.
D'un autre côté, la Customer
classe suppose comment il va être utilisé - dans ce cas, il sera utilisé dans une liste triée par noms.
IComparable
est utilisé implicitement
En comparaison avec les alternatives, il est très difficile de voir où la logique de comparaison est utilisée - ou pas du tout. En supposant votre IDE standard et à partir de la Customer
classe, je devrai
- Rechercher toutes les références à
Customer
- Trouvez les références utilisées dans une liste
- Vérifiez si ces listes ont déjà fait
.Sort()
appel à elles
Ce qui est probablement pire, si vous supprimez une IComparable
implémentation qui est toujours utilisée, vous n'obtenez aucune erreur ou avertissement. La seule chose que vous obtiendrez est un mauvais comportement dans tous les endroits qui étaient trop obscurs pour que vous y pensiez.
Ces problèmes combinés, ainsi que l'évolution des exigences
La raison même pour laquelle j'ai pensé à cela, c'est parce que ça a mal tourné pour moi. J'utilise heureusement IComparable
mon application depuis 2 ans maintenant. Maintenant, les exigences ont changé et la chose doit être triée de 2 manières différentes. Il a remarqué qu'il n'est pas amusant de suivre les étapes décrites dans la section précédente.
La question
Ces problèmes me font penser IComparable
comme inférieur IComparer
ou .OrderBy()
, au point de ne voir aucun cas d'utilisation valide qui ne serait pas mieux servi par les alternatives.
Est-il toujours préférable d'utiliser IComparer
ou LINQ, ou y a-t-il des avantages / cas d'utilisation que je ne vois pas ici?
la source
IComparable
plus, ce qui renforce mon argument.SortedXXX
collections, elles nécessitent soit que les éléments stockés le soient,IComparable
soit qu'ils soientIComparer
fournis. Notez également qu'il est trivial d'inverser l'ordre de tri naturel avec un comparateur et de le faire fonctionner avec tous lesIComparable
objets.IComparable
est considéré comme le mécanisme de comparaison par défaut .IComparer
est utilisé lorsque vous souhaitez remplacer le mécanisme de comparaison par défaut.ReverseComparer<T>
: gist.github.com/jackfarrington/078e7af7bc82482aa634Réponses:
IComparable
a les restrictions que vous avez mentionnées, c'est exact. Il s'agit d'une interface qui était déjà disponible dans .NET Framework 1.0, où ces alternatives fonctionnelles et Linq n'étaient pas disponibles. Donc oui, on pourrait le voir comme un élément de framework obsolète qui est principalement conservé pour une compatibilité ascendante.Cependant, pour de nombreuses structures de données simples, une méthode de tri est probablement suffisante ou naturelle. Pour ces cas, avoir un endroit canonique pour implémenter la relation d'ordre est toujours un bon moyen de garder le code SEC, au lieu de répéter toujours la même logique dans chaque appel à
OrderBy
partout.Vous utilisez «heureusement IComparable dans votre application depuis 2 ans maintenant», comme vous l'avez écrit, il me semble donc que cela vous a bien servi pendant longtemps. Lorsque vous devez maintenant valider, modifier et tester tous les appels vers
Sort
, cela peut également être un signe que vous faisiez le même type de logique de tri à de nombreux endroits, ce qui n'est pas la fauteIComparable
. Cela pourrait donc être l'occasion de centraliser davantage cette logique en un seul endroit, rendant votre code plus SEC.la source
IComparable
, tout le code de tri préexistant aurait été laissé intact dans leurs vues respectives, alors que je ne ferais qu'ajouter un nouveau code de tri pour la nouvelle vue.IComparable
implémentation que vous avez écrite?IComparable
, vous obtenez gratuitement une implémentation par défaut, et parfois vous n'avez même pas besoin d'écrire cette implémentation.BigInteger
. S'il n'implémentait pas d' opérateurs / interfaces de comparaison, comment implémenteriez-vous même un IComparer vous - même ? Vous auriez besoin d'accéder aux structures de données internes pour le faire efficacement, ou pas du tout. Supposons que vous ayez un type comme Client; les propriétés publiques que vous souhaitez trier do ont comparateurs. Pour moi, c'est la différence: implémenterIComparable<T>
s'il serait déraisonnable de s'attendre à ce que l'appelant implémente un comparateur.If I hadn't used IComparable, all the pre-existing sorting code would have been left untouched in their respective views, while I'd only add new sorting code for the new view.
CeIComparable
n'est pas parce que c'était une meilleure solution à l'époque que c'est la meilleure solution aujourd'hui . Votre premier commentaire ici implique que "c'est IComparable ou rien", ce qui n'est pas vrai, le problème aurait pu être résolu de différentes manières. Les applications peuvent croître en taille / échelle, et les choses qui semblaient convenables peuvent ne pas être en mesure de répondre aux demandes croissantes de l'application.Je suis d'accord avec vos sentiments
IComparable
Regardez les remarques sur
Array.Sort()
IComparable
interface pour pouvoir effectuer des comparaisons avec tous les autres éléments du tableau. (ou une exception est levée)Nous n'aurons probablement jamais la motivation maintenant, cependant! envisager
object.Equals()
une méthode sur chaque objet qui vous permet de comparer les objets les uns avec les autres pour voir s'ils sont "identiques"Vous l'avez déjà là, mais vous avez été chargé d'ajouter que
Array.Sort()
vous voudrez peut-être ajouterobject.Compare(object)
la source