Pregunta

I would like to confirm the expanation to some things I've been trying to understand.

I have two scenarios:

Scenario 1: I have one list stored in a private field of my class, I make a deep copy of it and store it in other private field. After doing so, I make some changes in the list, but I can choose to retrieve its original state. For doing so, I assign the copy of the original listto the modified one:

Public Class ClassX
    Private myList As List(Of Double)
    Private myOriginalList As List(Of Double)

    Public Sub New()
        myList = New List(Of Double)
        myOriginalList = ObjectCopier.Clone(myList)
    End Sub

    Private Sub Main()
        ChangeMyList()
        'myList  has one element
        RevertChanges()
        'myList  has zero elements
    End Sub

    Public Sub ChangeMyList()
        Dim r As New Random
        myList.Add(r.NextDouble)
    End Sub

    Public Sub RevertChanges()
       myList = myOriginalList 
    End Sub
End Class

Doing so, makes everything work as I would expect.

Scenario 2: The idea is pretty much the same, make a deep copy of one list for allowing the retrieval of its original state. However, in this case, the list is passed to another object, which makes a deep copy of it, modifies it, and decides to save those changes or revert them. And by doing so, I cannot get the desired behaviour, since the list is changed even when I make the assignment "myList = myOriginalList". Code:

Public Class ClassX
    Private myList As List(Of Double)

    Private Sub Main()
        Dim myList As New List(Of Double)
        Dim c As New ClassY(myList)

        c.ChangeList()
        'myList has one element
        c.RevertChanges()
        'myList still has one element

    End Sub
End Class

Public Class ClassY
    Private myList As List(Of Double)
    Private myOriginalList As List(Of Double)

    Public Sub New(ByVal c As List(Of Double))
        myList = c
        myOriginalList = ObjectCopier.Clone(myList)
    End Sub

    Public Sub ChangeList()
        Dim r As New Random
        myList.Add(r.NextDouble)
    End Sub

    Public Sub RevertChanges()
        myList = myOriginalList
    End Sub
End Class

So the question is... why? Why can I revert changes this way in the first case, but not in the second? Why changes made to the list passed as reference to ClassY are saved, but an assignment is not transmited to the original list in ClassX?

Hope it makes sense! Thanks!

¿Fue útil?

Solución

I have adapted your code to avoid same variable's name as myList and c.

I have also implemented ObjectCopier() so that VB.Net code is testable for other readers.

Using following code

Module MainModule

    Public Class ObjectCopier
        Public Shared Function Clone(ByRef lst As List(Of Double)) As List(Of Double)
            Return lst.AsEnumerable().ToList()
        End Function
    End Class

    Private myList As List(Of Double)

    Public Sub Main()
        Dim myList As New List(Of Double)

        Dim c As New ClassY(myList)

        Console.WriteLine(">> mylist.Count(): " & CStr(myList.Count()))
        Console.WriteLine(">> c.myClasslist.Count(): " & CStr(c.myClassList.Count()))
        Console.WriteLine(">> c.myOriginalList.Count(): " & CStr(c.myOriginalList.Count()))

        c.ChangeList()

        Console.WriteLine(">> mylist.Count(): " & CStr(myList.Count()))
        Console.WriteLine(">> c.myClasslist.Count(): " & CStr(c.myClassList.Count()))
        Console.WriteLine(">> c.myOriginalList.Count(): " & CStr(c.myOriginalList.Count()))

        c.RevertChanges()

        Console.WriteLine(">> mylist.Count(): " & CStr(myList.Count()))
        Console.WriteLine(">> c.myClasslist.Count(): " & CStr(c.myClassList.Count()))
        Console.WriteLine(">> c.myOriginalList.Count(): " & CStr(c.myOriginalList.Count()))
    End Sub

    Public Class ClassY
        Public myClassList As List(Of Double)
        Public myOriginalList As List(Of Double)

        Public Sub New(ByVal lst As List(Of Double))
            myClassList = lst
            myOriginalList = ObjectCopier.Clone(myClassList)
        End Sub

        Public Sub ChangeList()
            myClassList.Add(1.0)
        End Sub

        Public Sub RevertChanges()
            myClassList = myOriginalList
        End Sub
    End Class

End Module

I get following result

>> mylist.Count(): 0
>> c.myClasslist.Count(): 0
>> c.myOriginalList.Count(): 0

>> mylist.Count(): 1
>> c.myClasslist.Count(): 1
>> c.myOriginalList.Count(): 0

>> mylist.Count(): 1
>> c.myClasslist.Count(): 0
>> c.myOriginalList.Count(): 0

As you can see, only c.myClassList.Count() is changed from 1 to 0 in RevertChanges() function.

Why ? Because before call of RevertChanges() function

myList         point to Address-X1
myClassList    point to Address-X1
myOriginalList point to Address-X3  

and after

myList         continue to point to Address-X1
myClassList    point to Address-X3
myOriginalList point to Address-X3 

Caution: If now, you add a new element to myClassList variable, you will change myOriginalList because you must clone myOriginalList to restore original value in myList !!!

To change myList, you must pass it by reference in RevertChanges() function.

Public Sub RevertChanges(ByRef lst As List(Of Double))
    myClassList = myOriginalList
    lst = myOriginalList
End Sub

or return new myClassList from RevertChanges() function and assign it to myList.

Public Function RevertChanges() as List(Of Double)
    myClassList = myOriginalList
    return MyClassList
End Function

myList = c.RevertChanges()

Otros consejos

Setting 'myList' in ClassY back to the original doesn't change 'myList' in the 'Main' method. Have 'RevertChanges' take a list parameter:

Public Sub RevertChanges(ByRef changedList As List(Of Double))
   myList = myOriginalList 
   changedList = myList
End Sub
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top