【问题标题】:Saving assignments in object passed by reference将分配保存在通过引用传递的对象中
【发布时间】:2014-04-08 14:57:59
【问题描述】:

我想确认对我一直试图理解的一些事情的扩展。

我有两种情况:

场景 1: 我有一个列表存储在我班级的私有字段中,我制作了一份深层副本并将其存储在其他私有字段中。这样做之后,我对列表进行了一些更改,但我可以选择检索其原始状态。为此,我将原始列表的副本分配给修改后的列表:

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

这样做,让一切如我所愿。

场景 2: 这个想法几乎相同,制作一个列表的深层副本以允许检索其原始状态。但是,在这种情况下,列表被传递给另一个对象,该对象对其进行深层复制,对其进行修改,并决定保存这些更改或恢复它们。通过这样做,我无法获得所需的行为,因为即使我进行分配“myList = myOriginalList”,列表也会更改。代码:

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

所以问题是……为什么?为什么我可以在第一种情况下以这种方式恢复更改,而在第二种情况下不能?为什么对作为引用传递给 ClassY 的列表所做的更改被保存,但分配没有传输到 ClassX 中的原始列表?

希望这是有道理的!谢谢!

【问题讨论】:

  • myList = myOriginalList 不会复制或还原它,它只是让两个对象引用同一个列表。如果那是您在ObjectCopier 中所做的,那么您没有制作副本,而是复制了对象引用
  • 在 ObjectCopier 中,我通过复制对象的序列化和反序列化来进行深度复制,因此它实际上是一个不同的对象,没有对前一个对象的引用。谢谢。
  • ObjectCopier 显然有问题,我们看不到该代码来判断您是否实际上返回了 New 列表(对于列表副本而言,序列化似乎很长的路要走)。另外,为什么 ClassX 不能继承 ClassY 而不是创建私有内部对象(不清楚 X 是否维护对 Y 的引用,如果那是真实的代码)?
  • 使用此代码,您无法再次还原。
  • 嗨。这不是我要编写的真实代码,它是简化的,但我试图理解的行为出现在这个简化的示例中。克隆器很像这个:stackoverflow.com/a/78612/2651069。当然,我知道复制列表的更好方法,这只是为了简化目的!

标签: vb.net pointers variable-assignment memento


【解决方案1】:

将 ClassY 中的 'myList' 设置回原来的值不会改变 'Main' 方法中的 'myList'。 让“RevertChanges”采用列表参数:

Public Sub RevertChanges(ByRef changedList As List(Of Double))
   myList = myOriginalList 
   changedList = myList
End Sub

【讨论】:

  • 我知道了,我想了解的是为什么在ClassY中给myList添加新元素会影响Main方法中的myList,但是将ClassY中的myList设置回原来的不影响Main方法中的myList .
  • 在'ChangeList'方法中,'myList'和'Main'中的'myList'仍然是同一个对象。在“RevertChanges”中,两个列表不同 - ClassY 中的一个指向不同的列表。
  • 啊哈!这就是我想的......但我仍然不明白为什么!是不是因为ClassY中的myList是指向Main中的myList的指针,但赋值后又指向另一个对象?是的,我想我明白了……
  • 尽管这并不完全正确,但将对象变量视为“地址”并将真实对象视为“房屋”可能会有所帮助 - 如果两个变量具有相同的“地址”,则更改由于地址相同,房屋的内容会改变在两个地址上看到的内容。改一个地址指向不同的房子,现在两者之间没有对应关系。
  • 非常感谢!我会将此标记为正确答案。
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 2017-09-11
  • 2013-08-11
  • 2020-12-06
相关资源
最近更新 更多