Paul Nations wrote:
I've got arraylists of simple classes bound to controls. I need to
search through those arraylists to set the correct SelectedItem in the
control. The code looks like:
Public Class DegreeMaintenance
Private arrCipCodes As New ArrayList
'populate reader with data
With rdr
Do While .Read
arrCipCodes.Add(New CipCode(.GetString(0),
..GetString(1))) Loop
.Close()
End With
arrCipCodes.Sort()
Public ReadOnly Property CipCodes() As ArrayList
Get
Return arrCipCodes
End Get
End Property
End Class
'************************************************* ****************
Public Class CipCode
Private myCipDisplay As String
Private myCipCode As String
Public Sub New(ByVal strCipDisplay As String, ByVal strCipCode As
String)
MyBase.new()
With Me
.myCipDisplay = strCipDisplay 'e.g. 01.9999
Agriculture, Agriculture Operations and Related Sciences, Other
.myCipCode = strCipCode 'e.g. 01.9999
End With
End Sub
Public ReadOnly Property CipDisplay() As String
Get
Return myCipDisplay
End Get
End Property
Public ReadOnly Property CipCode() As String
Get
Return myCipCode
End Get
End Property
End Class
'************************************************* ***************
And finally in a form is this code:
'
Me.cbCipCode.SelectedIndex =
DegreeMaintenance.CipCodes.BinarySearch(dd.CipDisp lay)
When I execute this line I get this message:
Additional information: Specified IComparer threw an exception.
I'm not sure where to go from here. Do I need to implement an
IComparer?
Yes. BinarySearch needs to be able to compare the objects in the
ArrayList in order to search it, and it doesn't know how to compare
CipCode's.
How do I search on the second element of the class members of my
arraylist?
TWO WAYS to do this:
a) First method: Define a class that compares CipCode's and implements
IComparer; supply one of these to BinarySearch:
Public Class CipCodeComparer
Implements IComparer
Public Function Compare(ByVal x As Object, ByVal y As Object) As
Integer Implements System.Collections.IComparer.Compare
'because we don't type check here -
'it becomes our responsibility to ensure that a CipCodeComparer
'is only ever used to compare CipCode's
Dim cx As CipCode = DirectCast(x, CipCode)
Dim cy As CipCode = DirectCast(y, CipCode)
Return String.Compare(cx.CipCode, cy.CipCode)
End Function
End Class
Hopefully this will be self-explanatory - this is a class whose sole
purpose is to provide an implementation of IComparer that compares
CipCode's by their CipCode property. Note that I have taken the
stylistic decision to explicitly passthrough to String.Compare; I could
just as easily have said
if cx.cipcode < cy.cipcode then
return -1
elseif cx.cipcode > cy.cipcode then
return 1
else
return 0
end if
I think just passing through to String.Compare better shows what is
being done.
Anyway, once you've defined this class, you just need to supply it to
BinarySearch using the appropriate overload:
Me.cbCipCode.SelectedIndex =
DegreeMaintenance.CipCodes.BinarySearch(dd.CipDisp lay, New
CipCodeComparer)
and you should be in business.
b) Second method: have CipCode implement IComparable, so that when the
default comparer (the one that gets used when no comparer is explicitly
mentioned in the call to BinarySearch) comes calling, comparisons will
be done as you want:
add to the definition of CipCode:
Implements IComparable
Public Function CompareTo(ByVal obj As Object) As Integer
Implements System.IComparable.CompareTo
Dim other As CipCode = DirectCast(obj, CipCode)
Return Me.CipCode.CompareTo(other.CipCode)
End Function
(as before, without type checking it's our responsibility to make sure
CipCode's are only ever compared to other CipCode's)
Now when you use the comparer-less overlod of BinarySearch, it will
know get a useful answer when it asks the CipCode's to compare amongst
themselves.
btw, be sure to check you're filling the ArrayList in Code order, as
BinarySearch assumes this.
--
Larry Lard
Replies to group please