2

我有一个 WPF 表单,它采用具有位置和大小的对象列表并将它们绘制在画布上。我目前正在尝试实现一个撤消按钮,该按钮将丢弃对对象位置所做的所有更改,并恢复为加载表单时检索到的原始集合。

就目前而言,我在加载表单时访问数据库并获取所有需要显示的对象,然后将返回的列表分配给两个单独的集合。出现的问题是这两个集合实际上是指向原始集合的指针,并且每当更改一个集合时,更改都会反映在第二个集合中。

是否可以复制对象列表,以便对一个集合所做的更改不会影响辅助集合?

到目前为止,我已经尝试简单地使用赋值运算符,将源集合传递给一个函数byval并滚动列表的每个元素,手动将其添加到第二个集合中,并使用 linq 从原始列表中获取所有对象并推送结果到一个单独的临时列表并将第二个集合分配给临时列表。

我觉得我把这个问题复杂化了,但我在谷歌搜索时遇到的几乎所有地方都说这种行为是设计使然,我理解,但这似乎是一个相当普遍的想法。

4

4 回答 4

2

这是我以前用来制作对象的“深度”副本的函数:

Public Function DeepCopy(ByVal ObjectToCopy As Object) As Object

    Using mem as New MemoryStream

        Dim bf As New BinaryFormatter
        bf.Serialize(mem, ObjectToCopy)

        mem.Seek(0, SeekOrigin.Begin)

        Return bf.Deserialize(mem)

    End Using

End Function

与其他一些答案相比,这是一种低级方法,但允许您深度复制任何对象。我已经在与您类似的情况下成功使用了它,我需要一个数组的深层副本。

于 2012-05-24T21:33:32.687 回答
1

只需使用此代码将 listA 的所有项目分配给 listB

For Each elm In ListA
   ListB.Add(elm) 
Next
于 2014-09-05T07:34:47.100 回答
0

此后删除了另一个答案,据说用于var copy = list.ToList();获取列表的副本。这将适用于以下警告:两个列表仍将引用相同的对象,因此对这些对象的任何更改都将反映在两个列表中。只要您只更改列表中对象的顺序,此解决方案就完全可行。

于 2012-05-24T20:53:30.627 回答
0

您必须创建一个新列表并将 list1 中的项目的副本添加到其中。您可以使用对象初始化来做到这一点,例如

Dim list2 = (From item in list1
             Select New ItemType With {.Property1 = item.Property1, .Property2 = item.Property2}.ToList()

另一种方法是将 Copy 构造函数添加到 ItemType

Public Sub New(item as ItemType)
    Me.Property1 = item.Property1
    Me.Property2 = item.Property2
End Sub

您的列表副本可以简化为

Dim list2 = (From item in list1
             Select New ItemType(item)}.ToList()

请注意,如果您的 ItemType 的任何属性是引用,您还需要制作这些对象的副本。(这称为深拷贝

于 2012-05-24T20:57:26.830 回答