Laden...

IComparable<T>, IComparer<T>, Comparison<T>: Welchen Einsatzzweck für was?

Erstellt von lutzeslife vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.833 Views
L
lutzeslife Themenstarter:in
155 Beiträge seit 2012
vor 10 Jahren
IComparable<T>, IComparer<T>, Comparison<T>: Welchen Einsatzzweck für was?

Hallo Leute,

vielleicht habe ich gerade ein Brett vor dem Kopf, aber so ganz komme ich nicht auf eine gerade Linie. Es gibt ja die 2 Interfaces sowie die Möglichkeit des Delegate um einen Vergleich von Objekten anzustellen. Die Frage ist aber wann nehme ich was für welchen Einsatzzweck.

IComparable<T>

Verwende ich innerhalb meiner Klasse (public class MyClass : IComparable<MyClass>) um innerhalb einer Liste oder eines Arrays List<MyClass>.Sort() verwenden kann. (Die parameterlose Sort() Variante!)
Dabei könnte ich sowohl die generische Variante mit einem konkreten Typ oder die nicht generischen Variante für CompareTo(object obj) verwenden.
Das leuchtet mir ein.

IComparer<T>

Wenn ich das richtig verstehe verwende ich ihn ob für verschiedene Vergleichskriterien einen Comparer bauen möchte.

class Myclass
{
public string Test1;
public string Test2;
}


class Test1Comparer:IComparer<MyClass>
class Test2Comparer:IComparer<MyClass>

List<MyClass>.Sort(new Test1Comparer());
List<MyClass>.Sort(new Test2Comparer());

Comparison<T>

Das ist eine Delegat um der Sort() Methode eine Methode zum Vergleich zu übergeben.


static int ComparisonExampleDo(Myclass c1,Myclass c2)

List<Myclass>.Sort(ComparisonExampleDo);

Für sich genommen leuchtet mir es ein, gerade wenn man IComparable<T> und IComparer<T> betrachten. Aber wann nehme ich besser ein IComparer<T> und eine Methode für Comparison<T>

Ich könnte das Beispiel von IComparer<T> ja auch mit Methoden abdecken:

static class MyClassComparer
{
public static int Test1Compare(Myclass c1, Myclass c2)
public static int Test2Compare(Myclass c1, Myclass c2)
} 

List<Myclass>.Sort(MyClassComparer.Test1Compare)
List<Myclass>.Sort(MyClassComparer.Test2Compare)

Die Frage ist also welchen Vorteil haben die Interface Implementierungen gegenüber der Delegate Implementierung? Persönlich könnte ich mir vorstellen das die man mit Methoden weniger Schreibkram hat als mit den Klassen für IComparer<T> und das nicht so viele Objekte erzeugt werden!

Wie seht ihr das so? Vielleicht übersehe ich ja auch etwas was von Bedeutung wäre?

Gruß
Daniel

P.S:

Habe gerade diesen Link noch gefunden: Guid to using IComparer<T> und Comparison<T>

Wenn ich mit meinem bescheiden Englisch das richtig verstehe ist die Comparison<T> Variante langsamer weil eine umwandlung in IComparer<T> erfolgt.

Mit freundlichen Grüßen
lutzeslife

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Fanfon,

IComparable<T> nimmst du, wenn es sowas wie eine native Sortierung für die Objekte gibt. Eine Art der Sortierung, die unter den vielen Arten, die Objekte der Klasse zu sortieren, herausragt. Die allgemein als die Standardsortierung angesehen wird. Bei natürlichen Zahlen wäre das die normale aufsteigende Sortierung nach dem Zahlenwert (1, 2, 3, ...).

Mehrere Comparer kannst du schreiben, wenn es verschiedene Arten der Sortierung gibt, die man immer wieder mal braucht. Bei Personen könnte es einen SurnameComparer, einen FullNameComparer und einen BirthdayComparer geben.

Comparison<T> hat den Vorteil, dass man schnell und einfach einen Lambda-Audruck hinschreiben kann, um eine bestimmte Sortierung zu erreichen. Ich denke, das ist der Hauptgrund, warum dieser Typ eingeführt wurde.

Über die Performance musste ich mir bisher noch keine Gedanken machen. Letztlich kann der Unterschied auch nur auf einen bestimmten (konstanten) Faktor(*) hinauslaufen, so dass hier keine prinzipielles Problem vorliegt. Darum muss man sich erst kümmern, wenn in einem konkreten Fall spürbare Performance-Probleme auftreten. Solange das nicht der Fall ist, gilt "premature optimization is the root of all evil". Viel wichtiger ist, dass der Code gut lesbar ist. Danach sollte man die Wahl des verwendeten Vergleichstyps treffen.

herbivore

(*) Möglicherweise wird der Unterschied in einer neuen Version des Frameworks beseitigt.

L
lutzeslife Themenstarter:in
155 Beiträge seit 2012
vor 10 Jahren

Hallo herbivore

danke für die Antwort.

Wenn ich mir das Beispiel zwischen IComparer<T> und Comparison<T> anschaue, scheint auch der Vorteil zu sein, dass perse man mehrer Objekte z.B. über den Konstrukteur der Comparerklasse mitgeben kann. Bei Comparison<T> muss die statische Methode oder der Lambda-Ausdruck je der Methodensignatur nach übereinstimmen also

public int Compare(T o1, T o2)

Was als Vorteil gesehen werden kann. Aber das Argument mit dem Lambda ist gut daran hab ich in dem Moment gar nicht gedacht. Der Lesbarkeit geschuldet sollte man aber wahrscheinlich auf große Codemengen an Vergleichen verzichten.

Zusammengefasst könnte man also sagen:

ICompareable<T>* native Sortierung z.B. aufsteigene Zahlreihen

Comparison<T>* schnelle Implementierung durch Lambda-Ausdrücke

  • Benutzung statische Methode möglich
  • bei Lambda möglicherweise schlecht lesbar

Comparer<T>* aufwendige Implementierungen

  • Übergabe weiterer Objekte/Informationen

Aus Sicht der Performance kann ich nicht viel sagen, da es in diesem konkreten Fall nicht eine primäre Rolle spielt da die Listen auch nicht lang sind, die es zu sortieren gilt.

Gruß
Daniel

P.S: Andere Meinungen sind herzlichst willkommen!

Mit freundlichen Grüßen
lutzeslife

5.941 Beiträge seit 2005
vor 10 Jahren

Hallo Daniel

Weitere Objekte / Informationen kannst du in allen Optionen mitgeben.
Bei IComparable indem du die betreffende Klasse so anpasst, sodass die Informationen in der Compare-Methode zur Verfügung stehen.

Und bei IComparison, indem du einfach verfügbare Objekte in den Lambda-Ausdruck übernimmst.

Ich denke ebenso wie herbivore, dass IComparison hauptsächlich wegen der Nutzung von Lambda, bzw anonymen Methoden eingebaut wurde.

Wenn es aber um Austauschbarkeit, Erweiterbarkeit geht und ggf. so eine Sortierung bzw. Vergleich komplexer wird, IComparer vor IComparison vorzuziehen ist. Denn dann hast du Instanzen und nicht irgendwelche freischwebenden Ausdrücke oder Referenzen auf statische / instanzbehaftete Methoden, wie bei IComparison.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011