Overriding the Equals method to find the IndexOf an item in an ArrayList

R

Rubbrecht Philippe

Hi there,

According to documentation I read the ArrayList.IndexOf method uses the
Object.Equals method to loop through the items in its list and locate the
first index of an item that returns True.

Therefore, overriding the Equals method in the class definition of the items
I put in the ArrayList should make the IndexOf method use my version of the
Equals method?!

However, this does not seem to work.
Using following code in a standard VB.NET Console application returns -1 as
a result of the IndexOf method. Am I doing something wrong here?!

Best regards,
Philippe Rubbrecht

Module Main

Sub Main()

'Create ArrayList and add a few items.

Dim lst As ArrayList = New ArrayList

Dim itm As ListItem

itm = New ListItem("BE", "Belgium") : lst.Add(itm)

itm = New ListItem("DE", "Germany") : lst.Add(itm)

itm = New ListItem("NL", "Nederland") : lst.Add(itm)

'Now try to find the index of an item using the overloaded Equals method.

Dim key As String = "DE"

'Now output the index of the last item added.

System.Console.WriteLine("Index for key '{0}' = {1}", key, lst.IndexOf(key))

'Hold.

System.Console.ReadLine()

End Sub

End Module

Public Class ListItem

Private mstrKey As String

Private mstrDescription As String

Public Sub New(ByVal key As String, ByVal description As String)

Me.mstrKey = key

Me.mstrDescription = description

End Sub

Public Property Key() As String

Get

Return Me.mstrKey

End Get

Set(ByVal Value As String)

Me.mstrKey = Value

End Set

End Property

Public Property Description() As String

Get

Return Me.mstrDescription

End Get

Set(ByVal Value As String)

Me.mstrDescription = Value

End Set

End Property

Public Overloads Overrides Function Equals(ByVal obj As Object) As Boolean

If obj.GetType Is GetType(ListItem) Then

Return CType(obj, ListItem).Key.Equals(Me.Key)

ElseIf obj.GetType Is GetType(String) Then

Return CType(obj, String).Equals(Me.Key)

Else

Return False

End If

End Function

End Class
 
O

One Handed Man

Maybe I missed something, but I did run your code and It is returning True
( -1 ) because it found the key ( and you are returning a boolean ) as it
test as being ListItem in Type, what did you expect to be returned ?

Regards - OHM
 
R

Rubbrecht Philippe

The IndexOf method should return the index of the first item that returns
True for the Equals method. In the sample, the IndexOf method should return
1 instead of -1 (this is the default answer when the item is not found).
 
O

One Handed Man

OK OK, I see the error now.

The index of was being passed the string ( NOT the object being searched for
Amended code below for test. I also changed the ListView class to ListView1.

OHM

'Create ArrayList and add a few items.

Dim lst As ArrayList = New ArrayList

Dim itm1, itm2, itm3 As ListItem1

itm1 = New ListItem1("BE", "Belgium") : lst.Add(itm1)

itm2 = New ListItem1("DE", "Germany") : lst.Add(itm2)

itm3 = New ListItem1("NL", "Nederland") : lst.Add(itm3)

'Now try to find the index of an item using the overloaded Equals method.

'***** NOTES THAT key now is set to an item2 - This search called the
overloaded and overridden function Equals ****

Dim key As ListItem1 = itm2

'Now output the index of the last item added.

System.Console.WriteLine("Index for key '{0}' = {1}", key, lst.IndexOf(key))

'Hold.

System.Console.ReadLine()
 
R

Rubbrecht Philippe

OK, you're right. It works because the standard Object.Equals method
verifies object references.
In both cases they are indeed equal if you pass the same object reference.

But the question was how you can override the Equals method to be able to
verify keys instead of object references!
 
O

One Handed Man [ OHM ]

Yes But the basic problem is this . . .

When IndexOf is called, each item in the arrayList is compared with the
object that is submitted for searching. Equals only gets called when two
objects are of the same type. ( Makes sense really doesent it, you cant
compare a string with an integer for ex ).

If you put

debug.writeline("Overriden function has been called")

In your overriden function of Equals , it never fires if you just put a
string type in. So you can either create search object which contrains the
value member you want to search on and code your override function to test
it or simply re-think your method.

For example.

dim si as New ListItem("Im searching for this","")

indexOf(si) ' Now your Overriden function gets called.


Regards - OHM
 
T

Tom Shelton

Hi there,

According to documentation I read the ArrayList.IndexOf method uses the
Object.Equals method to loop through the items in its list and locate the
first index of an item that returns True.

Therefore, overriding the Equals method in the class definition of the items
I put in the ArrayList should make the IndexOf method use my version of the
Equals method?!

However, this does not seem to work.
Using following code in a standard VB.NET Console application returns -1 as
a result of the IndexOf method. Am I doing something wrong here?!

Best regards,
Philippe Rubbrecht

<snip>

It doesn't work because arraylist is not calling your Equals function.
It calls the shared method Object.Equals - not the member Equals. In
other words, it is calling:

Object.Equalse(obj, yourobject)

You can't override that :) Actually, since your looking these up by
keys, why are you not using a hashtable? That's what they are used for
:)

Dim h As New Hashtable
Dim itm As ListItem

itm = new ListItem("BE", "Belgium") : h.Add(itm.Key, itm)
itm = new ListItem("DE", "Denmark") : h.Add(itm.Key, itm)
itm = new ListItem("NL", "Netherland") : h.Add(itm.Key, itm)

Dim key As String = "DE"

If h.Contains(key) Then
itm = h(key)
Console.WriteLine(itm.Description)
Else
Console.WriteLine("Item Not Found")
End If

HTH
 
O

One Handed Man

Actually you can override the Equals method. I tested it See my other post.

OHM
 
T

Tom Shelton

Actually you can override the Equals method. I tested it See my other post.

OHM

Yes, you can - the instance method. The problem is that
ArrayList.IndexOf isn't calling the instance method. Put a
break point in your Equals - it never gets called. That's
because the ArrayList.IndexOf is calling the class method
Equals. That you can't override, because it is a member of
the class, not your instance... Am I clear?
 
O

One Handed Man

I'm referring to the Equals methods of the instances of the Objects in the
List. I did put a breakpoint in the overriden functions and they do get
called provided that the object being passed to IndexOf has other objects of
the same class in the List of objects contained in the ArrayList, this makes
perfect sense to me.

.. . . .Am I Clear ?

OHM
 
T

Tom Shelton

I'm referring to the Equals methods of the instances of the Objects in the
List. I did put a breakpoint in the overriden functions and they do get
called provided that the object being passed to IndexOf has other objects of
the same class in the List of objects contained in the ArrayList, this makes
perfect sense to me.

. . . .Am I Clear ?

OHM

On further investigation - you do indeed appear to be correct. So, I
apologize if I have offended you - though that was never my intention.

If you call it using a string, then the overridden equals is never
called (which is what I was trying), but if you pass in a ListItem,
then it is. And you can then do a value comparison. Which means
that the ArrayList.IndexOf is only calling the instance equals if the
types match....

So, this doesn't work...

Dim key As String = "DE"
Console.WriteLine ("Index for key '{0}' = {1}", key, lst.IndexOf(key))

But, this does:

Dim key As New ListItem("DE", String.Empty)
Console.WriteLine( _
"Index for key '{0}' = {1}", key.Key, lst.IndexOf(key))

Still, I believe the OP would be better off using a hashtable, since
that is really what it looks like he is trying to accomplish anyway.
 
O

One Handed Man

Hi Tom,
No offence taken, we are in agreement. At the end of the day,
facts are all thats count.

Best Regards - OHM
 
R

Rubbrecht Philippe

I know, in the sample I gave I would be better of using a hashtable.
But I just posted this as a sample of what I was trying to do.... overriding
the Equals method to find items in an arraylist.

I know now I have to supply an object of the same type to have the IndexOf
method use my overridden version of the Equals method.
Although I believe that this is not a necessary requirement if you try to
find an item in the Items list of a ComboBox for example? I have to check
this myself to be 100% sure about this, though!

Thanks for the info!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top