|
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
21.4.1. System.Collections.IComparerNaast de IComparable interface bestaat er ook een IComparer interface, of voluit System.Collections.IComparer. Deze interface is bruikbaar om "comparers" van af te leiden die definiëren hoe verschillende objecten van een bepaald type worden vergeleken.
Deze interface is vrij eenvoudig, en heeft slechts één member, namelijk Compare : Public Interface IComparer Function Compare(ByVal x As Object, ByVal y As Object) As Integer End Interface Deze comparer objecten kan men bijvoorbeeld doorgeven aan Sort methods, van bijvoorbeeld de Array klasse, om aan te geven dat men van het normale vergelijkingsgedrag, gedefinieerd door de IComparable.CompareTo implementatie, wil gaan afwijken.
De returnwaarde van deze Compare method zou : - negatief ( < 0 ) moeten zijn indien x "kleiner" is dan y - nul moeten zijn indien x "gelijk" is aan y - positief ( > 0 ) moeten zijn indien x "groter" is dan y
Kleiner, groter of gelijk moet je niet letterlijk nemen. In deze context van een sorteermethod wordt daar bijvoorbeeld mee bedoeld dat ze respectievelijk voor, na of op dezelfde ordinale plaats komen.
In onderstaand voorbeeld zie je hoe bij de eerste call naar Array.Sort (1), de Counter elementen gewoon worden gesorteerd op basis van hun Value. Dit is immers wat de IComparable.CompareTo implementatie had aangegeven.
De call naar Array.Sort met een IComparer argumentwaarde (2), zal hier de Counter elementen sorteren op hun StepValue, wat door de implementatie van de IComparer.Compare method is aangegeven. Visual Basic 2010 Broncode Option Strict OnImports System.Collections Namespace IComparerInterface Public Class Counter : Implements IComparable Public Sub New( ByVal value As Integer) _Value = value _StepValue = 1 End Sub Private _Value As Integer Public ReadOnly Property Value() As Integer Get Value = _Value End Get End Property Private _StepValue As Integer Public Property StepValue() As Integer Get StepValue = _StepValue End Get Set( ByVal value As Integer) _StepValue = value End Set End Property Public Sub Raise() _Value += StepValue End Sub Public Overrides Function ToString() As String ToString = Value.ToString() & "/" & StepValue.ToString() End Function Private Function CompareTo( ByVal obj As Object) As Integer _ Implements IComparable. CompareTo If Not TypeOf obj Is Counter Then Throw New ArgumentException( "An invalid argument was " & _ "specified. An argument of type Counter is required.") Else CompareTo = CompareTo( DirectCast(obj, Counter)) End If End Function Public Function CompareTo( ByVal other As Counter) As Integer If other IsNot Nothing Then CompareTo = 1 Else CompareTo = Me.Value.CompareTo(other.Value) End If End Function End Class Public Class CounterStepValueComparer : Implements IComparer Public Function Compare( ByVal x As Object, ByVal y As Object) _ As Integer Implements IComparer. Compare If x IsNot Nothing AndAlso y Is Nothing Then Return 1 ElseIf x Is Nothing AndAlso y IsNot Nothing Then Return -1 ElseIf x IsNot Nothing AndAlso y IsNot Nothing Then If TypeOf x Is Counter AndAlso TypeOf y Is Counter Then Dim a As Counter = DirectCast(x, Counter) Dim b As Counter = DirectCast(y, Counter) Compare = a.StepValue.CompareTo(b.StepValue) Else Throw New ArgumentException( "x and y are of different " & _ "types and neither one can handle comparisons with the other.") End If End If End Function End Class Public Class Client Public Shared Sub Main() Dim array1 As Counter() = _ New Counter() { New Counter(1) With {.StepValue = 3}, _ New Counter(2) With {.StepValue = 2}, _ New Counter(3) With {.StepValue = 1}} Array.Sort(array1) PrintArray(array1) Dim comparer1 As IComparer = New CounterStepValueComparer Array.Sort(array1, comparer1) PrintArray(array1) Console.ReadLine() End Sub Public Shared Sub PrintArray( ByVal array As Array) For Each element As Object In array Console.Write(element.ToString() & " ") Next Console.WriteLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 1/3 2/2 3/1
3/1 2/2 1/3 Elke object wordt als "groter" beschouwd dan Nothing ( (3) en (4) ).
Indien men toch probeert objecten van onvergelijkbare types te vergelijken, dan treedt er typisch een ArgumentException op (5).
Het werken met comparer objecten is ook van toepassing indien je bijvoorbeeld niet beschikt over de sourcecode van de itemtype, maar toch wil gaan aangeven op basis van wat, elementen van dat type, worden gesorteerd. boven
21.4.2. System.Collections.Generic.IComparer(Of T)De System.Collections.IComparer interface is niet strongly typed. Je kan aan de Compare method argumentwaardes meegeven van eender welk type gezien er gewerkt wordt met Object parameters.
Een strongly typed variant van IComparer is de System.Collections.Generic.IComparer(Of T) interface, deze wordt verderop behandeld in het hoofdstuk over genericiteit. boven
21.4.3. System.Collections.Generic.CaseInsensitiveComparerWe hoeven ook niet altijd zelf een comparer te definiëren, er bestaan immers een aantal voorgedefinieerd, bijvoorbeeld de System.Collections.Generic.CaseInsensitiveComparer klasse die reeds de IComparer interface implementeren.
Deze zal Strings vergelijken zonder rekening te houden met hoofdletters of kleine letters : Visual Basic 2010 Broncode Namespace CaseInsensitiveComparerExample Public Class Client Public Shared Sub Main() Dim array1 As String() = New String() { "B", "b", "a", "A"} Array.Sort(array1) IComparerInterface.Client.PrintArray(array1) Array.Sort(array1, New CaseInsensitiveComparer) IComparerInterface.Client.PrintArray(array1) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output a A b B
A a B b
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|