ようこそ。睡眠不足なプログラマのチラ裏です。

IClonableインターフェイスとMemberwiseCloneメソッド

今日は、.NETにおけるクローンオブジェクトなお勉強です。


インスタンスの中身をコピーする方法は、大きく分けて3つあります。
1つは、何も考えずにインスタンス内のメンバを手動でコピーする方法。
2つ目は、System.Reflectionを利用して、メンバをコピーする方法。


もう1つは、System.Object.MemberwiseCloneメソッドを使用する方法です。
このメソッドは、.NET Freamwork1.1では(オプションの設定によっては)インテリセンス表示されないので、
ご存知ない方も多いみたいです。基本的なことではありますが、ライバルに差をつけろ!的な意気込みで、
知らなかった方は、これを機会に覚えておきましょう。


System.Object.MemberwiseCloneメソッドは、一般的に
System.IClonableインターフェイスを実装して利用されます。
実装することになる System.ICloneable.Cloneメソッドの戻り値は、System.Object 型となっています。
戻り値が System.Object 型ということは、利用する側でキャストをしなければならない。これはめんどい。
なので、System.ICloneable.Cloneメソッドは Private宣言し、これをラップしたPublicメソッドを作り、
戻り値をClone対象のクラスと同じ型としたラッパーメソッドを作りましょう。

[VB.NET]
Public Class Person
  Implements System.ICloneable

  Public Name As String
  Public Age As Integer

  Private Function Clone() As Object Implements System.ICloneable.Clone
    Return Me.MemberwiseClone()
  End Function

  Public Function ShallowCopy() As Person
    Return DirectCast(Me.Clone(), Person)
  End Function
End Class

てな感じです。

System.Object.MemberwiseCloneメソッドは、俗に言う「浅いコピー」であり、
上記の例のような値型のメンバしか含まれない場合は、特に注意する必要はないが、
参照型のメンバを含むような場合は、参照先のインスタンスそのものはコピーされないことに注意する必要がある。
浅いコピー(ShallowCopy)での参照型のコピーは、参照先を示すアドレス、
いわゆるポインタ (参照) がコピーされます。


参照型のメンバのインスタンスそのものをコピーしたいような場合は、
浅いコピー(ShallowCopy)ではなく、深いコピー(DeepCopy)を行います。
深いコピー(DeepCopy)をするには、いったん浅いコピー(ShallowCopy)をした後に、
参照型のメンバをクローンコピーすることで実現することができます。


詳しくはオマケ参照ということで(・公・)

オマケ
IClonableインターフェイスを使ってみる(System.Object.MemberwiseCloneメソッドの利用) - VB.NET - 雑なサンプルソース