对象的深拷贝

9

我可以帮您进行对象的深拷贝。

这是我的代码:

Option Explicit On
Option Strict On

<Serializable> Public Class [Class]
Private _Name As String
Private _ListOfFields As New List(Of Field)

Public Property Name As String
    Get
        Return _Name
    End Get
    Set(value As String)
        _Name = value
    End Set
End Property

Public Property ListOfFields As List(Of Field)
    Get
        Return _ListOfFields
    End Get
    Set(value As List(Of Field))
        _ListOfFields = value
    End Set
End Property

Public Function Clone() As [Class]
    Return DirectCast(Me.MemberwiseClone, [Class])
End Function

End Class

Field是我自己写的一个类。

我需要修改什么才能使Clone()函数返回深度拷贝?


使用UltraMapper https://maurosampietro.github.io/UltraMapper/ - Mauro Sampietro
2个回答

9
任何类都可以通过调用此帮助函数来创建一个克隆:
Function DeepClone(Of T)(ByRef orig As T) As T

    ' Don't serialize a null object, simply return the default for that object
    If (Object.ReferenceEquals(orig, Nothing)) Then Return Nothing

    Dim formatter As New BinaryFormatter()
    Dim stream As New MemoryStream()

    formatter.Serialize(stream, orig)
    stream.Seek(0, SeekOrigin.Begin)

    Return CType(formatter.Deserialize(stream), T)

End Function

这是通过将类中的所有信息序列化为可移植对象,然后重写它以断开任何引用指针来实现的。

注意:传入的类及其公开为属性的任何其他类都必须标记为<Serializable()>才能使用BinaryFormatter.Serialize

如果您想使自己的类自行公开可克隆方法,则可以添加该方法并实现ICloneable接口,如下所示:

<Serializable()>
Public Class MyClass : Implements ICloneable

    'NOTE - The Account class must also be Serializable
    Public Property PersonAccount as Account
    Public Property FirstName As String

    Function Clone(ByRef orig As MyClass) As MyClass Implements ICloneable.Clone

        ' Don't serialize a null object, simply return the default for that object
        If (Object.ReferenceEquals(orig, Nothing)) Then Return Nothing

        Dim formatter As New BinaryFormatter()
        Dim stream As New MemoryStream()

        formatter.Serialize(stream, orig)
        stream.Seek(0, SeekOrigin.Begin)

        Return CType(formatter.Deserialize(stream), T)

    End Function

End Class

注意:要知道 ICloneable 带来了它自己的争议,因为它不会向调用者指示它是否执行深层克隆或浅层克隆。实际上,您不需要这个接口来将该方法添加到您的类中。

6

(顺带一提,我可能会将您的类命名为其他名称而不是“Class”)。

如果您想全手动实现,您需要按照以下步骤操作:

  1. 确保您的Field类还实现了深度复制Clone()方法。如果您还没有这样做,那么这通常需要其Clone()方法创建一个新的Field类型对象,然后根据当前对象填充其每个属性。如果您的Field类具有其他类/复杂类型(例如您自己创建的类)的属性,则它们也应该实现Clone()方法,并且您应该调用Clone()方法来创建新的深层副本。
  2. 在类的Clone()方法中,您将创建一个[Class]类型的新对象,例如通过调用其构造函数
  3. 将新对象的Name属性设置为当前对象的Name属性
  4. 创建一个新的List(Of Field),以便示例中称之为listA
  5. 遍历当前列表并将每个列表项的克隆分配给listA。例如:

For Each item in _ListOfFields
    listA.Add(item.Clone())
End

  1. 然后,您可以将新列表(listA)分配给在 Clone()方法中创建的对象。

还有一种可能更好的手动方法是使用VB.NET描述的深层复制技术

如果您想要作弊一点,那么您可以对现有对象进行序列化,然后将其反序列化为新对象,就像这里描述的技术一样。

我认为序列化和反序列化的技术是最“简单”的一种方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接