Changing a Structure that's in an ArrayList

A

Adam

Hi all,

In my VB.NET code below, I try to change the user name in my arraylist from
Ted to Bob, but instead it adds a new user to the arraylist named Bob. Can
anyone explain why this happens and how I might modify a structure in an
arraylist without having to completely remove it and re-add the structure to
the arraylist? I just want to iterate throught the arraylist and change
items based on certain conditions.

Thanks in advance!


Public Structure user
Dim name As String
End Structure

Module Module1

Dim users As ArrayList = New ArrayList
Dim ouser As user

Sub Main()
ouser.name = "Ted"
users.Add(ouser)

For Each ouser In users
ouser.name = "Bob"
Next

users.Add(ouser)

For Each ouser In users
Console.WriteLine(ouser.name)
Next

Console.ReadLine()
End Sub

End Module
 
J

Jay B. Harlow [MVP - Outlook]

Adam,
Remember that a structure is a Value Type, and the ArrayList holds objects,
which means when you add the Structure to an array list a copy is made, as
the Structure is boxed (changed into an object) when you access (Index into
the arraylist) a copy is made. When you use the For Each, a copy is made.

So in the line "user.name = "bob"" you are modifying a copy of the
structure.

To get this to work you need to use an indexed for loop, remove the
structure from the arraylist and put the structure back in, something like:

Dim index As Integer
For index = 0 to users.Count -1 ouser = users(index)
ouser.name = "Bob" users(index) = ouser
Next

Alternately I would recommend using a Class instead of a Structure, as the
Class is a reference type, which means when you add an instance of the Class
to the ArrayList a copy of the reference is made, when you use a For Each a
copy of the reference is returned, which means you can use a For Each as
expected.

Something like:
Public Class user
Dim name As String

Public Sub New(ByVal name As String)
Me.Name = name
End Sub
End Class

Module Module1

Dim users As ArrayList = New ArrayList

Sub Main()
Dim ouser As user
ouser = New User("Ted")
users.Add(ouser)

For Each ouser In users
ouser.name = "Bob"
Next

users.Add(New User("Bill"))

For Each ouser In users
Console.WriteLine(ouser.name)
Next

Console.ReadLine()
End Sub

End Module


Hope this helps
Jay
 
C

Cor

In addition to Jay,

Remove that extra add, I was puzzling on it, but never do something with
structures, because I knew that Jay would sure answer this when I did I did
not answer you, because that was not the only problem and I did not want to
give you an alternative but was curious also.

Thanks Jay I think I see it now, I did first send this message before to
check because I did not see that wrong extra add in your message, but that
was not the problem alone.

Cor
 
C

Cor

Hi,

This is it (with the structure with an alternative it was no problem)
:)
\\\
Public Structure user
Dim name As String
End Structure
Module Module1
Dim users As ArrayList = New ArrayList
Dim ouser As user
Sub Main()
ouser.name = "Ted"
users.Add(ouser)
Dim index As Integer
For index = 0 To users.Count - 1
ouser = DirectCast(users(index), user)
ouser.name = "Bob"
users(index) = ouser
Next
' users.Add(ouser)
For Each ouser In users
Console.WriteLine(ouser.name)
Next
Console.ReadLine()
End Sub
End Module
///
 
S

Scott

See the comments below....

Adam said:
Hi all,

In my VB.NET code below, I try to change the user name in my arraylist from
Ted to Bob, but instead it adds a new user to the arraylist named Bob. Can
anyone explain why this happens and how I might modify a structure in an
arraylist without having to completely remove it and re-add the structure to
the arraylist? I just want to iterate throught the arraylist and change
items based on certain conditions.

Thanks in advance!


Public Structure user
Dim name As String
End Structure

Module Module1

Dim users As ArrayList = New ArrayList
Dim ouser As user

Sub Main()
ouser.name = "Ted"
users.Add(ouser)
For Each ouser In users
ouser.name = "Bob"
Next

The routine above is not actually accessing the objects in the ArrayList
directly. It is simply setting the value of "ouser" to the value of the
current object in the list. Therefore, when you manipulate the data you are
only modifying the copy. The line below then adds the copy into the
ArrayList as a new object.
users.Add(ouser)

To modify the data directly you would need to use a routine similar to the
one below:

Dim i as integer
For i = users.Count - 1 To 0 Step -1
users.Item(i).name = "Bob"
Next

You may not need to iterate the ArrayList in reverse order if you're not
adding or removing items. However, if you do either of these you will need
to go in reverse order or the routine will throw an error because the list
has been modified.

I haven't checked any of this code, but it should work or at least give you
some ideas....
 
J

Jay B. Harlow [MVP - Outlook]

Scott,
users.Item(i).name = "Bob"
Did you try this? You get an exception, as you cannot operate on a structure
Late Bound!

If you add a DirectCast to avoid the late binding, you then get an error!.

For details on why it won't work see my response...

Hope this helps
Jay
 
A

Adam

I did what Cor suggested and it worked great. Thanks all for the help!
Reference types vs. Value types can be trciky at first. Here's what was
suggested and what worked for me:



Hi,

This is it (with the structure with an alternative it was no problem)
:)
\\\
Public Structure user
Dim name As String
End Structure
Module Module1
Dim users As ArrayList = New ArrayList
Dim ouser As user
Sub Main()
ouser.name = "Ted"
users.Add(ouser)
Dim index As Integer
For index = 0 To users.Count - 1
ouser = DirectCast(users(index), user)
ouser.name = "Bob"
users(index) = ouser
Next
' users.Add(ouser)
For Each ouser In users
Console.WriteLine(ouser.name)
Next
Console.ReadLine()
End Sub
End Module
///
 

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