你可以通过两种方式进行深度克隆:通过实现ICloneable接口(并调用Object.MemberwiseClone方法),或通过二进制序列化。
第一种方式
第一种方式(可能更快,但不总是最好的)是在每种类型中实现ICloneable接口。下面的示例说明了这一点。类C实现了ICloneable接口,因为该类引用了其他类D和E,所以后者也实现了这个接口。在C的Clone方法中,我们调用其他类型的Clone方法。
Public Class C
Implements ICloneable
Dim a As Integer
' Reference-type fields:
Dim d As D
Dim e As E
Private Function Clone() As Object Implements System.ICloneable.Clone
' Shallow copy:
Dim copy As C = CType(Me.MemberwiseClone, C)
' Deep copy: Copy the reference types of this object:
If copy.d IsNot Nothing Then copy.d = CType(d.Clone, D)
If copy.e IsNot Nothing Then copy.e = CType(e.Clone, E)
Return copy
End Function
End Class
Public Class D
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Me.MemberwiseClone()
End Function
End Class
Public Class E
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Me.MemberwiseClone()
End Function
End Class
现在,当您调用C类实例的Clone方法时,您将获得该实例的深度克隆:
Dim c1 As New C
Dim c2 As C = CType(c1.Clone, C) ' Deep cloning. c1 and c2 point to two different
' locations in memory, while their values are the
' same at the moment. Changing a value of one of
' these objects will NOT affect the other.
注意:如果类D和E具有引用类型,则必须像我们为类C所做的那样实现它们的Clone方法。依此类推。
警告:
1-上面的示例只有在没有循环引用的情况下才有效。例如,如果类C具有自我引用(例如,一个字段是C类型),则实现ICloneable接口将不容易,因为C中的Clone方法可能会进入无限循环。
2-另一件需要注意的事情是MemberwiseClone方法是Object类的Protected方法。这意味着您只能从类的代码内部使用此方法,如上所示。这意味着您不能将其用于外部类。
因此,仅当不存在上述两个警告时,实现ICloneable才是有效的。否则,您应该使用二进制序列化技术。
第二种方法:
二进制序列化可用于深层克隆,而不会出现上述问题(特别是循环引用)。以下是执行深层克隆的通用方法,使用二进制序列化:
Public Class Cloning
Public Shared Function DeepClone(Of T)(ByVal obj As T) As T
Using MStrm As New MemoryStream(100) ' Create a memory stream.
' Create a binary formatter:
Dim BF As New BinaryFormatter(Nothing, New StreamingContext(StreamingContextStates.Clone))
BF.Serialize(MStrm, obj) ' Serialize the object into MStrm.
' Seek the beginning of the stream, and then deserialize MStrm:
MStrm.Seek(0, SeekOrigin.Begin)
Return CType(BF.Deserialize(MStrm), T)
End Using
End Function
End Class
以下是如何使用此方法:
Dim c1 As New C
Dim c2 As C = Cloning.DeepClone(Of C)(c1) ' Deep cloning of c1 into c2. No need to
' worry about circular references!