vb.netimplementationicloneable

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


Solution

  • 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