Sortieren mit dem IComparer Interface
Geschrieben von: Christoph Wille In vielen Fällen sind die Elemente in einer Collection nicht so angeordnet, wie man sie gerne hätte. Oft möchte man auch zur Laufzeit eine Umsortierung erzwingen, zB die Elemente aufsteigend statt absteigend sortieren. Anhand der Sort Methode der ArrayList Klasse zeige ich, daß dies nicht weiter schwierig ist. Die Sort Methode der ArrayList Klasse hat mehrere Overloads, und an einige kann ein Comparer übergeben werden, der das IComparer Interface implementiert. Dieses Interface hat nur eine einzige Methode - Compare. Dieser werden zwei Objekte x und y übergeben, und je nach dem wie die beiden Objekte vergleichen, sieht der Rückgabewert wie folgt aus:
Ich möchte das gleich an einem Beispiel verdeutlichen: /// <summary>Implements ascending sort algorithm</summary> public class AscendingComparer : IComparer { public int Compare(object objA, object objB) { return String.Compare(objA.ToString(), objB.ToString()); } } Die Klasse AscendingComparer implementiert das IComparer Interface, und besitzt eine einzige Methode, nämlich Compare. Dieser Methode werden zwei Objekte übergeben, und der Vergleich zwischen beiden wird mittels String.Compare durchgeführt (wir sortieren also Strings). Diese liefert - wie der Zufall es so will - die gleichen Rückgabewerte wie die Compare Methode von IComparer. Will man einen DescendingComparer implementieren, muß man nur die Parameter an String.Compare in der umgekehrten Reihenfolge übergeben: /// <summary>Implements descending sort algorithm</summary> public class DescendingComparer : IComparer { public int Compare(object objA, object objB) { return String.Compare(objB.ToString(), objA.ToString()); } } Damit hätten wir zwei Comparer zum Experimentieren zur Verfügung. Zur Demonstration wird eine ArrayList einmal unsortiert, aufsteigend und schließlich absteigend sortiert ausgegeben: public static void Main(string[] args) { // fill a sample array list ArrayList al = new ArrayList(); ComparerSampleMain.FillArrayList(ref al); // print the unsorted list Console.WriteLine("-- Unsorted --"); foreach(string strCurrent in al) { Console.WriteLine(strCurrent); } // sort ascending, then print al.Sort(new AscendingComparer()); Console.WriteLine("\r\n-- Sorted ascending --"); for (int i=0; i < al.Count; i++) { Console.WriteLine(al[i]); } // finally, sort descending, then print al.Sort(new DescendingComparer()); Console.WriteLine("\r\n-- Sorted descending --"); foreach(string strCurrent in al) { Console.WriteLine(strCurrent); } } Der Sort Methode wird jeweils eine Instanz des gewünschten Comparers übergeben: al.Sort(new AscendingComparer()); Und Sort verwendet dann diesen Comparer, um während des Umsortierens die Vergleiche zwischen zwei Elementen vorzunehmen. Umsortieren ist also keine Hexerei unter .NET. Automatische Klassengenerierung in SharpDevelopNatürlich kann man bei so einem einfachen Interface wie IComparer leicht den notwendigen Infrastrukturcode selbst schreiben. Sobald ein Interface aber mehr als drei Methoden hat, wird diese Arbeit allerdings lästig, und kostet Zeit, die wir zum Schreiben der Implementierung besser verwenden könnten. Also Zeit, daß uns ein Tool die Aufgabe der Vorgenerierung des Klassengrundgerüsts abnimmt. In SharpDevelop gibt es einen Class Wizard, der genau das kann, und zwar sowohl für C# und auch VB.NET. Und zu demonstrieren, wie einfach das geht, fügen wir dem aktuellen Projekt einfach eine neue Datei dazu: In der New File Dialogbox wählen wir in der Gruppe C# den New Class Wizard aus. Unsere erste Entscheidung ist der Klassenname (hier MySpecialComparer). Die Klasse, die generiert wird, soll public sein, und wir leiten von keiner Basisklasse ab (keine Auswahl in Available Base Classes): Mit Next geht es weiter im Wizard. Jetzt folgt die Auswahl der Interfaces, die wir in der Klasse MySpecialComparer implementieren wollen. Hier ist IComparer aus dem System.Collections Namespace bereits ausgewählt: Damit sind wir fast fertig. Auf der letzten Wizardseite können wir noch unseren bevorzugten Programmierstil auswählen, und auch diverse (Open Source) Lizenzen automatisiert einfügen lassen. Der wichtigste Punkt aber sind die drei Checkboxen, die die ganze Coding-Arbeit für uns übernehmen: Damit ist der Wizard auch schon fertig, und generiert uns folgenden Code (einige Kommentare sind zur Verkürzung herausgenommen): namespace IComparerSample { using System; /// <summary> /// TODO - Add class summary /// </summary> /// <remarks> /// created by - Administrator /// created on - 4/16/2002 1:13:33 PM /// </remarks> public class MySpecialComparer : object, System.Collections.IComparer { /// <summary> /// Default constructor - initializes all fields to default values /// </summary> public MySpecialComparer() { } /// <summary> /// TODO - add method description /// </summary> /// <remarks> /// Interface method from IComparer /// /// </remarks> /// <param name='x'>TODO - add parameter description</param> /// <param name='y'>TODO - add parameter description</param> public virtual int Compare(object x, object y) { throw new System.NotImplementedException(); } } } Neben einem vollständigen Klassengrundgerüst bekommen wir auch gleich die entsprechende vorausgefüllte XML Dokumentation mitgeneriert. Durch die Verwendung dieses Wizards kann man bei der Implementierung von Klassen einiges an Zeit einsparen! SchlußbemerkungDie Implementierung des IComparer Interfaces ist schnell möglich. Wer mehrere Interfaces (oder größere) implementieren möchte, sollte sich SharpDevelop und den New Class Wizard genauer anschauen. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
Arrays mit Index und Schlüssel Links zu anderen SitesWenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |