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() 函数才能返回深层副本?

4

2 回答 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存在争议,因为它不会向调用者指示它是执行深层克隆还是浅层克隆。实际上,您不需要接口就可以将方法添加到您的类中。

于 2015-03-09T19:07:28.563 回答
6

(顺便说一句,我可能会将您的班级命名为“班级”以外的名称)。

如果您想手动完成所有操作,则需要执行以下步骤:

  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 中有一种替代(可能更好)的手动方法。

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

我会说先序列化然后反序列化技术是“最简单”的技术。

于 2013-03-23T06:49:05.560 回答