Monochromatic
Monochromatic

Reputation: 309

vb .net swallow ICloneable implementation

I know there's tons of question on the matter. But I couldn't, for the life of me, make any sense of the answers or use them in my example. I am newish in vb .net and I can't really implement general examples to my specific one. What I have is basically this:

dim a as New list(of player)
EDIT: dim b as New list(of player)    'previously was: dim b as new player

Class player
    Public name As String
    '[more]
End Class

[....]

a.Add(New player)
b.Add(New player)
a(0).name="john"
b=a
a(0).name="jack"
msgbox(b(0).name) 'it will print jack instead of john

I now this can be done with ICloneable, but after reading up a lot on it I can't implement correctly. Thank you in advance

Upvotes: 0

Views: 257

Answers (1)

Mary
Mary

Reputation: 15091

When you assign a(0) to b they are both pointing to the same object in memory. Even though you declared b as New player that new player was thrown away when you made the assignment to an existing player.

To prove this to yourself, try the opposite. Change the name property of b and you will see it is reflected in the name property of a(0).

Private Sub OPCode()
    Dim a As New List(Of player)
    Dim b As player
    a.Add(New player)
    a(0).name = "john"
    b = a(0)
    b.name = "jack"
    MsgBox(a(0).name) 'jack
End Sub

Now to Clone...

Class player
    Implements ICloneable
    Public name As String
    '[more]
    Public Function Clone() As Object Implements ICloneable.Clone
        Dim p As New player
        p.name = name
        Return p
    End Function
End Class

Your class now implements ICloneable with the addition of the Clone function. You can implement this however you wish as long as the signature of the function matches the interface signature for the Clone method.

Notice that my implementation is creating a New player and is assigning the name property to the name of the existing player. This New player is what is returned by the function. The New player will have a different location in memory so changes to the first player from the list and this new player will not affect each other.

Since the Clone function returns an object, we need to cast it to player (the underlying type) so it will match our declare of b and we will be able to use the properties and methods of the player class.

Private Sub OPCode()
    Dim a As New List(Of player)
    Dim b As player
    a.Add(New player)
    a(0).name = "john"
    b = CType(a(0).Clone, player)
    a(0).name = "jack"
    MsgBox(b.name) 'john
End Sub

EDIT

To accomplish your goal using 2 lists, I created a new class called PlayerList. It inherits List(Of Player) and implements ICloneable. You can now clone list a and get completely separate lists with composed of separate player objects.

Public Class PlayerList
    Inherits List(Of player)
    Implements ICloneable
    Public Function Clone() As Object Implements ICloneable.Clone
        Dim newList As New PlayerList
        For Each p As player In Me
            Dim newP = CType(p.Clone(), player)
            newList.Add(newP)
        Next
        Return newList
    End Function
End Class

Private Sub OPCode()
    Dim a As New PlayerList()
    Dim b As PlayerList
    a.Add(New player)
    a(0).name = "john"
    b = CType(a.Clone, PlayerList)
    a(0).name = "jack"
    MsgBox(b(0).name)
End Sub

Upvotes: 1

Related Questions