Neulich beim Programmieren hatte ich das Anliegen, Klasseninstanzen, die in einer ArrayList gespeichert waren, zu sortieren. Natürlich nicht irgendwie, sondern nach einem bestimmten Feld, das ich zur Compilezeit noch nicht kenne, das aber zur Ausführzeit bekannt wird. Die Testklasse heißt schlicht "Schiff": <Serializable()> Public Class Schiff Implements IComparable ' (1) Public Name As String Public Heimathafen As String Public Baujahr As Integer Public Kaufpreis As Single Public Stapellauf As New Date Public Shared SortierFeld As String = "Heimathafen" ' (2) Public Shared Sortierung As SortOrder = SortOrder.Ascending Public Sub New(ByVal Name As String, ByVal Heimathafen As String, _ ByVal Baujahr As Integer, ByVal Kaufpreis As Single, ByVal Stapellauf As Date) Me.Name = Name Me.Heimathafen = Heimathafen Me.Baujahr = Baujahr Me.Kaufpreis = Kaufpreis Me.Stapellauf = Stapellauf End Sub Public Sub New() End Sub Public Function CompareTo(ByVal obj As Object) _ As Integer Implements System.IComparable.CompareTo ' (3) Dim s As Schiff s = CType(obj, Schiff) Dim f1 As Reflection.FieldInfo f1 = Me.GetType.GetField(Me.SortierFeld) Dim f2 As Reflection.FieldInfo f2 = s.GetType.GetField(Me.SortierFeld) Wert1 = f1.GetValue(Me) Wert2 = f2.GetValue(s) If Wert1 Is Nothing Or Wert2 Is Nothing Then Exit Function ' (4) ' (5) If f1.FieldType Is GetType(Integer) Or f1.FieldType Is GetType(Short) Or f1.FieldType Is GetType(Long) Then If Wert1 > Wert2 Then Return 1 ElseIf Wert1 < Wert2 Then Return -1 Else Return 0 End If ElseIf f1.FieldType Is GetType(Double) Or f1.FieldType Is GetType(Single) Then If Wert1 > Wert2 Then Return 1 ElseIf Wert1 < Wert2 Then Return -1 Else Return 0 End If ElseIf f1.FieldType Is GetType(String) Then Return String.Compare(Wert1, Wert2) ElseIf f1.FieldType Is GetType(Date) Then Return Date.Compare(Wert1, Wert2) ElseIf f1.FieldType Is GetType(Decimal) Then Return Decimal.Compare(Wert1, Wert2) ElseIf f1.FieldType Is GetType(DateTime) Then Return DateTime.Compare(Wert1, Wert2) End If End Function End Class (1): implements IComparable brauchen wir für das Überschreiben der "CompareTo"-Methode, die die Hauptarbeit beim Sortieren für uns erledigt. (2): interessant sind hier die beiden "shared"-Variablen, mit denen wir nachher den Sortiervorgang steuern. Natürlich könnte man das ganze auch in einen Verwalter auslagern, aber der Einfachheit halber habe ich das gleich in der Klasse selber gemacht. In "SortierFeld" gibt man einfach den Namen des Feldes an, nach dem wir sortieren wollen. "Sortierung" gibt an, ob wir aufsteigend oder absteigend sortieren wollen, aber dazu später mehr. (3): Das Herzstück der Sortierung ist diese Funktion, die wir über die Implementierung der Schnittstelle "IComparable" einfach überschreiben. Wir holen uns zuerst die Werte der beiden Felder, die wir über die Klassenvariable "Sortierfeld" bestimmt haben. (f1 und f2 sind Verweise auf die jeweiligen Klassenelemente) Man beachte, dass einer der Vergleichswerte in der aktuellen Instanz ruht (Me) und der andere von außen als Parameter kommt. Wir vergleichen also quasi das Haus des Nachbarn mit unserem eigenen (4): falls eins der Felder nichts zurückgibt, dann steigen wir aus. Ein Grund hierfür wäre beispielsweise die Nicht-Existenz des Feldes! Dies kann vorliegen, falls in der ArrayList Instanzen von verschiedenen Klassen gespeichert sind. (5): nun folgen die von uns implementierten Vergleiche. Ganzzahlvergleiche werden der Bequemlichkeit halber zusammengefasst. Hier kann man auch eigene Definitionen einbringen, etwa eine Rundung auf zwei Nachkommastellen bei single, vier bei double, Missachtung von negativem Vorzeichen oder dergleichen. Bei den komplexeren Datentypen verwenden wir einfach die bereits existierenden Compare-Methoden gemäß dem Prinzip des intelligenten Faulseins Nun ein Beispiel zur praktischen Anwendung: ' Das einzige, was wir tun müssen, ist festzulegen, wonach wir ' sortieren wollen. Hier im Beispiel suchen wir uns einfach mal ' das Baujahr aus und wir wollen absteigende Resultate erhalten. Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Schiff.SortierFeld = "Baujahr" Schiff.Sortierung = SortOrder.Descending End Sub ' Diese Funktion wurde hier einem Steuerelement zugewiesen, nach dessen Klick ' der Code ausgeführt wird. (geht natürlich auch anders, etwa mit Hilfe eines ' eigenen Verwalters, der die Daten hält; sprengt jetzt aber vielleicht etwas den Rahmen) Private Sub Sortieren_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Sortieren.Click ' Erstellen einiger Instanzen Dim s1 As New Schiff("Albatros", "Rostock", 1864, 492.9, New Date(1863, 3, 5)) Dim s2 As New Schiff("Ubena von Bremen", "Bremen", 1380, 482.5, New Date(1379, 8, 27)) Dim s3 As New Schiff("Adler von Lübeck", "Lübeck", 1565, 285.7, New Date(1563, 12, 9)) Dim s4 As New Schiff("Rath von Riga", "Riga", 1341, 450.34, New Date(1340, 11, 24)) ' Füllen der ArrayList mit den Schiffen Dim AL As New ArrayList AL.Add(s1) AL.Add(s2) AL.Add(s3) AL.Add(s4) AL.Sort() ' Das tolle bei der ganzen Sache ist, dass wir die eigentliche Sortierung ' nicht programmieren müssen, denn das kann die ArrayList ganz allein. ' Wir müssen lediglich sagen, nach welchen Gesichtspunkten zwei Instanzen ' unserer eigenen Klasse verglichen werden sollen. ' dies wiederum haben wir in der CompareTo-Methode schon gemacht. ' Die Arbeit des sortierens erfolgt intern mit Aufruf von "sort". If Schiff.Sortierung = SortOrder.Descending Then AL.Reverse() 'wir sortieren immer aufsteigend und drehen bei Bedarf um End If ' Ausgabe um zu sehen, was passiert ist Dim s As String s = AL.Item(0).Name & " " & AL.Item(0).Baujahr & " " & _ AL.Item(0).kaufpreis & vbNewLine s &= AL.Item(1).Name & " " & AL.Item(1).Baujahr & " " & _ AL.Item(1).kaufpreis & vbNewLine s &= AL.Item(2).Name & " " & AL.Item(2).Baujahr & " " & _ AL.Item(2).kaufpreis & vbNewLine s &= AL.Item(3).Name & " " & AL.Item(3).Baujahr & " " & _ AL.Item(3).kaufpreis & vbNewLine MsgBox(s) End Sub Dieser Tipp wurde bereits 20.030 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
Neu! sevCommand 4.0 Professionelle Schaltflächen im modernen Design! Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. Tipp des Monats November 2024 Dieter Otter WAVE-Dateien aufnehmen Ein Code-Ausschnitt, mit dem sich WAVE-Dateien in verschiedenen Aufnahmequalitäten aufnehmen lassen. TOP Entwickler-Paket TOP-Preis!! Mit der Developer CD erhalten Sie insgesamt 24 Entwickler- komponenten und Windows-DLLs. Die Einzelkomponenten haben einen Gesamtwert von 1605.50 EUR... |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |