深いクローン作成は、ICloneableの実装(およびObject.MemberwiseCloneメソッドの呼び出し)またはバイナリシリアル化の2つの方法で行うことができます。
最初の方法
最初の(そしておそらくより速く、常にではないが最善)の方法は、各タイプで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のフィールド)を持つ場合、CのCloneメソッドは無限ループに入る可能性があるため、ICloneableインターフェイスの実装は容易ではありません。
2もう1つ注目すべきことは、MemberwiseCloneメソッドがObjectクラスのProtectedメソッドであることです。これは、上記のように、クラスのコード内からのみこのメソッドを使用できることを意味します。つまり、外部クラスには使用できません。
したがって、ICloneableの実装は、上記の2つの警告が存在しない場合にのみ有効です。それ以外の場合は、バイナリシリアル化手法を使用する必要があります。
第二の方法
バイナリシリアライゼーション(特に循環参照)上記問題なく深いクローニングのために使用することができます。ここでは、バイナリシリアル化を使用して、深いクローニングを行い、一般的な方法があります:
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!
すべてのICloneable? –
これは特定のオブジェクトだけを複製しています。このオブジェクトは、アプリの中核となるデータオブジェクトです。これはあなたの質問に答えますか? –