オブジェクトの複製
C#は自作クラスはすべて参照型として扱われます。 ですのでインスタンスを別のインスタンスにコピーしたとき、コピーされるのは実体ではなく、参照情報となります。これをシャローコピーと言います。
public class MyObject { public int hoge; public MyObject(int hoge) { this.hoge = hoge; } }
MyObject obj1 = new MyObject(1); MyObject obj2 = obj1; //コピーされるのは参照情報 obj2.hoge = 4; //obj2の値を変えると Console.WriteLine(obj1.hoge); //同じ参照先だからobj1も4になってしまう
ですが、自作クラスのオブジェクトの複製をしたいときがあります。
そのようなときにICloneableインターフェースを使用します。
ICloneable
ICloneableでは、「Cloneメソッドによってオブジェクトが複製されること」を保証します。
なので、ICloneableインターフェースを実装するクラスは、Cloneメソッドでオブジェクトを複製し、別の参照先となる同じオブジェクトを複製しなければなりません。これをディープコピーと言います。
public class MyObject:ICloneable { public int hoge; public MyObject(int hoge) { this.hoge = hoge; } public object Clone() { return new MyObject(this.hoge); //同じものを複製する } }
これであとはCloneメソッドを実行すると、新しい参照先にオブジェクトが複製され、ディープコピーが実現されます。
class Program { static void Main(string[] args) { MyObject obj1 = new MyObject(1); MyObject obj2 = (MyObject)obj1.Clone(); //新しい参照先が代入される obj2.hoge = 4; //obj2の値を変えると Console.WriteLine(obj1.hoge); //チガウ参照先だから値が変化しない } }
まとめ
追記
LINQ神ことMVP for VisualC#のneueccさんいわく、ICloneableインタフェースはレガシーインターフェースらしく、今では推奨されていないらしいです。
なのでオブジェクトのディープコピーをするときは、それ用のメソッドを用意するかコピーコンストラクタなどをつくるとよいらしいです。