IComparable
funktioniert nur in eine Richtung
Angenommen, Sie haben eine Employee
Klasse. In einer Ansicht möchten Sie alle Employees
nach Namen sortiert anzeigen - in einer anderen nach Adresse. Wie wirst du das erreichen? Nicht mit IComparable
, zumindest nicht in irgendeiner Weise.
IComparable
hat die Logik am falschen Ort
Die Schnittstelle wird durch Aufruf verwendet .Sort()
. In einer Ansicht, die Customer
nach Namen sortiert angezeigt wird, gibt es überhaupt keinen Code, der impliziert, wie er sortiert werden soll.
Andererseits geht die Customer
Klasse davon aus, wie sie verwendet werden soll - in diesem Fall wird sie in einer nach Namen sortierten Liste verwendet.
IComparable
wird implizit verwendet
Im Vergleich zu den Alternativen ist es sehr schwierig zu erkennen, wo die Vergleichslogik verwendet wird - oder wenn überhaupt. Unter der Annahme Ihrer Standard-IDE und ausgehend von der Customer
Klasse muss ich
- Suchen Sie nach allen Verweisen auf
Customer
- Suchen Sie die Referenzen, die in einer Liste verwendet werden
- Überprüfen Sie, ob diese Listen sie jemals
.Sort()
aufgerufen haben
Was wahrscheinlich schlimmer ist, wenn Sie eine IComparable
Implementierung entfernen , die noch verwendet wird, erhalten Sie keine Fehler oder Warnungen. Das einzige, was Sie bekommen, ist falsches Verhalten an allen Orten, die zu dunkel waren, als dass Sie daran denken könnten.
Diese Probleme zusammen mit sich ändernden Anforderungen
Der Grund, warum ich darüber nachgedacht habe, ist, dass es für mich schief gelaufen ist. Ich benutze IComparable
meine Anwendung seit 2 Jahren gerne . Jetzt haben sich die Anforderungen geändert und das Ding muss auf zwei verschiedene Arten sortiert werden. Es ist aufgefallen, dass es keinen Spaß macht, die im vorherigen Abschnitt beschriebenen Schritte durchzugehen.
Die Frage
Diese Probleme lassen mich IComparable
als minderwertig IComparer
oder .OrderBy()
bis zu dem Punkt denken , dass ich keinen gültigen Anwendungsfall sehe, der durch die Alternativen nicht besser bedient werden könnte.
Ist es immer besser, IComparer
oder LINQ zu verwenden, oder gibt es Vorteile / Anwendungsfälle, die ich hier nicht sehe?
quelle
IComparable
mehr verwenden, was meinen Standpunkt verstärkt.SortedXXX
Sammlungen entweder die gespeicherten Elemente vorhanden sein müssenIComparable
oderIComparer
bereitgestellt werden müssen. Beachten Sie auch, dass es trivial ist, die natürliche Sortierreihenfolge mit einem Vergleicher umzukehren und mit allenIComparable
Objekten arbeiten zu lassen.IComparable
wird als Standardvergleichsmechanismus angesehen .IComparer
wird verwendet, wenn Sie den Standardvergleichsmechanismus überschreiben möchten.ReverseComparer<T>
: gist.github.com/jackfarrington/078e7af7bc82482aa634Antworten:
IComparable
hat die Einschränkungen, die Sie erwähnt haben, das ist richtig. Es ist eine Schnittstelle, die bereits in .NET Framework 1.0 verfügbar war, wo diese funktionalen Alternativen und Linq nicht verfügbar waren. Ja, man könnte es als veraltetes Framework-Element betrachten, das hauptsächlich aus Gründen der Abwärtskompatibilität beibehalten wird.Für viele einfache Datenstrukturen ist jedoch eine Art der Sortierung wahrscheinlich ausreichend oder natürlich. In diesen Fällen ist ein kanonischer Ort zum Implementieren der Ordnungsbeziehung immer noch eine gute Möglichkeit, den Code DRY zu halten, anstatt immer die gleiche Logik bei jedem Aufruf an den
OrderBy
gesamten Ort zu wiederholen .Sie haben "IComparable seit 2 Jahren gerne in Ihrer Anwendung verwendet", wie Sie geschrieben haben, und es scheint mir, dass es Ihnen lange Zeit gute Dienste geleistet hat. Wenn Sie jetzt alle Anrufe validieren, ändern und testen müssen
Sort
, kann dies auch ein Zeichen dafür sein, dass Sie an vielen Stellen dieselbe Art von Sortierlogik ausgeführt haben, was nicht die Schuld von istIComparable
. Dies könnte also eine Gelegenheit sein, mehr von dieser Logik an einem Ort zu zentralisieren und Ihren Code trockener zu machen.quelle
IComparable
, wäre der gesamte bereits vorhandene Sortiercode in den jeweiligen Ansichten unberührt geblieben, während ich nur neuen Sortiercode für die neue Ansicht hinzugefügt hätte.IComparable
Ihnen geschriebene Implementierung korrekt funktioniert ?IComparable
Sie eine kostenlose Standardimplementierung, und manchmal müssen Sie diese Implementierung nicht einmal schreiben.BigInteger
. Wenn es keine Vergleichsoperatoren / -schnittstellen implementieren würde, wie würden Sie selbst einen IComparer implementieren ? Sie benötigen Zugriff auf die internen Datenstrukturen, um dies effizient oder überhaupt zu tun. Angenommen, Sie haben einen Typ wie Kunde. Die öffentlichen Objekte, nach denen Sie sortieren möchten, verfügen über Vergleicher. Für mich ist das der Unterschied: Implementieren,IComparable<T>
wenn es nicht zumutbar wäre, vom Aufrufer die Implementierung eines Vergleichers zu erwarten.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.
Nur weilIComparable
es zu dieser Zeit eine bessere Lösung war , heißt das nicht, dass es heute die beste Lösung ist . Ihr erster Kommentar hier impliziert, dass "es ist unvergleichbar oder nichts", was nicht wahr ist, das Problem hätte auf viele verschiedene Arten gelöst werden können. Anwendungen können an Größe / Umfang zunehmen, und Dinge, die früher geeignet aussahen, können möglicherweise nicht mit den steigenden Anforderungen der Anwendung Schritt halten.Ich stimme Ihren Ansichten zu
IComparable
Schauen Sie sich einfach die Anmerkungen zu an
Array.Sort()
IComparable
Schnittstelle implementieren , um Vergleiche mit jedem anderen Element im Array durchführen zu können. (oder Ausnahme wird ausgelöst)Wir werden jetzt aber wahrscheinlich nie die Motivation haben! Betrachten Sie
object.Equals()
eine Methode für jedes Objekt, mit der Sie Objekte miteinander vergleichen können, um festzustellen, ob sie "gleich" sind.Sie haben das bereits dort, wurden jedoch mit dem Hinzufügen beauftragt, das
Array.Sort()
Sie möglicherweise hinzufügen möchtenobject.Compare(object)
quelle