Related collections of objects

G

Guest

I’m in need of some remedial instruction collections of objects. I doubt if
this question is specific to pocket pc and VB, but that’s where I’m coding.

When I create a collection, call it collection A, and then create a new
collection B, if I make a change to one of the items in collection B, the
exact same changes effect collection A. While I could see this as being a
feature, for what I’m doing… well, I wish it wouldn’t. Is there some simple
way that I can “sever†the linkage between these two collections?
Here’s an example of the problem

Dim Vegetables As New Collection
Dim NewVegetables As New Collection

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
LoadVeggies()
NewVegetables = Vegetables
Dim Vegetable0 As New Vegetable
For Each Vegetable0 In NewVegetables
If Vegetable0.Name = "Squash" Then
Vegetable0.Color = "Green"
End If
Next
End Sub
Private Sub LoadVeggies()
Dim vegetableA As New Vegetable
vegetableA.Name = "Carrot"
vegetableA.Color = "Orange"
Vegetables.Add(vegetableA)

Dim vegetableB As New Vegetable
vegetableB.Name = "Squash"
vegetableB.Color = "Yellow"
Vegetables.Add(vegetableB)

End Sub
End Class
In this code, when I set a brake pt at the end sub for the Form 1 load, I’d
like to see the If logic create only a green Squash in NewVegetables. The
Yellow Squash should stay in Vegetables. It doesn’t, I get a green squash in
both collections. Some how the two collections are linked and I need to
sever the link. Suggestions?
 
M

Matt

Your problem is that you set NewVegetables equal to Vegetables. Because
they are not 'simple' types (like a string or integer), a reference is
made to the original rather than a copy being made. Here is an
optimization of your code with the fix:

Dim Vegetables As New Collection
Dim NewVegetables As New Collection

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
LoadVeggies()
For Each Veg as Vegetable In Vegetables
NewVegetables.Add(Veg)
Next
Vegetables.Clear
For Each Vegetable0 As Vegetable In NewVegetables
If Vegetable0.Name = "Squash" Then
Vegetable0.Color = "Green"
End If
Next
End Sub
Private Sub LoadVeggies()
Dim vegetableA As New Vegetable
vegetableA.Name = "Carrot"
vegetableA.Color = "Orange"
Vegetables.Add(vegetableA)

Dim vegetableB As New Vegetable
vegetableB.Name = "Squash"
vegetableB.Color = "Yellow"
Vegetables.Add(vegetableB)

End Sub
End Class
 
G

Guest

Matt thanks, but I tried your code sample, and still got a bad result.
Collection "vegtables" was identical to collection "newvegtables".... both
contained "green squash" when only "newvegtables" should have.

I tried this where i started, as a pocketpc ap, and then again as a windows
ap.

something that might be telling: "Vegtables.clear" as a command was
rejected on my system as a valid command. perhaps we have different
environments?

hmmm.... any guidance would be appreciated
 
C

Chris Dunaway

You have duplicated the same problem. Your For loop simply copies the
references to the new vegetable collection.
 
C

Chris Dunaway

Dave J wrote:

What Matt said is correct.
Dim Vegetables As New Collection
Dim NewVegetables As New Collection

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
LoadVeggies()
NewVegetables = Vegetables

The line above simply assigns the reference to the Vegetable collection
to the NewVegetables collection. In other words, they both point to
the *same* collection. You need this line:

NewVegetables = New VegetableCollection

Do as Matt suggested but make sure you are making copies of the
vegetable objects by adding a Clone method to your Vegetable class (see
below):

For Each v As Vegetable In Vegetables
Dim NewVeg As Vegetable = v.Clone
NewVegetables.Add(NewVeg)
Next
Dim Vegetable0 As New Vegetable
For Each Vegetable0 In NewVegetables
If Vegetable0.Name = "Squash" Then
Vegetable0.Color = "Green"
End If
Next
End Sub
Private Sub LoadVeggies()
Dim vegetableA As New Vegetable
vegetableA.Name = "Carrot"
vegetableA.Color = "Orange"
Vegetables.Add(vegetableA)

Dim vegetableB As New Vegetable
vegetableB.Name = "Squash"
vegetableB.Color = "Yellow"
Vegetables.Add(vegetableB)

You then need to add a Clone method to your Vegetable class:

Public Function Clone() As Vegetable
Dim v As New Vegetable
v.Name = Me.Name
v.Color = Me.Color
Return v
End Function
End Sub
End Class

This should fix the problem.

Chris
 
G

Guest

Thanks Chris:
I got your solution to work, but omitted the line:
NewVegetables = New VegetableCollection
my system didn't like this or variations such as
NewVegetables = New Vegetables Collection
Its kind of a moot pt, in that the code is running, but can you clarify on
what this line was intended to do.
thanks
 
C

Chris Dunaway

I just assumed you had some sort of Collection class so I guessed at
the name 'VegetableCollection'. It was just a guess on my part.
Somewhere you need to create a new 'Vegetables' container using
whatever name is appropriate for your project.
 

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