前回の ICloneable と MemberwiseClone からの続きです。
シャローコピー (Shallow Copy) と、ディープコピー (Deep Copy) について書きます。
前回の記事で、System.Object.MemberwiseClone メソッドでクローン コピーする場合、
参照型のメンバについては、参照先のインスタンスそのものがコピーされるのではなく、
参照先を示すアドレスがコピーされるだけであるということを書きました。
つまり、コピー元もコピー先も結局は同じものを指し示していることを意味します。
このようなクローン コピーを、シャローコピー (Shallow Copy、簡易コピー、浅いコピーなど) と言います。
逆に、参照先のインスタンスをも複製する場合は、ディープコピー (Deep Copy、深いコピーなど) と言います。
こうやって書くと、シャローコピーが (「簡易コピー」という名称なので) 劣っているかのように見えますが、
シャローコピーを使うか、ディープコピーを使うかは臨機応変であり、劣っているわけではありません。
次に、MemberwiseClone メソッドを使ったシャローコピーと、ディープコピーの例を示します。
前回と同様、System.ICloneable インターフェイスを実装して、複製できることを明示します。
VB.NET
Option Strict On
' テスト用のデータクラス (System.ICloneable インターフェイスを実装)
Public Class WankumaMember : Implements System.ICloneable
' 面倒なのでフィールド メンバにしちゃってます
Public MemberCode As Integer
Public MemberName As String
Public Age As Integer
Public Skills As New System.Collections.ArrayList() '参照型
Public Version As New System.Version() '参照型
' シャローコピー (Shallow Copy)
Public Function ShallowCopy() As WankumaMember
Return DirectCast(Me.Clone(), WankumaMember)
End Function
' ディープコピー (Deep Copy)
Public Function DeepCopy() As WankumaMember
' まずは簡易コピーしたものを格納
Dim hWankuma As WankumaMember = DirectCast(Me.Clone(), WankumaMember)
' 参照型のメンバをクローン コピーする
hWankuma.Skills = DirectCast(Me.Skills.Clone(), System.Collections.ArrayList)
hWankuma.Version = DirectCast(Me.Version.Clone(), System.Version)
Return hWankuma
End Function
' System.ICloneable.Clone メソッド (非公開メンバとする)
Private Function Clone() As Object Implements System.ICloneable.Clone
Return Me.MemberwiseClone()
End Function
End Class
シャローコピー側はそのままの実装で、MemberwiseClone メソッドの戻り値を同クラスの型に変換しているだけです。
ディープコピーについては、一旦簡易コピーした後に、参照型のメンバ (Skills、Version) をクローン コピーしています。
このようにオブジェクトのコピーは、手動によるコピーと、シャローコピー、ディープコピーがあります。
まあ、コレクションやデータクラスでないと普通は使わないとは思いますが、臨機応変に使い分けてください。