Long-Slow-Distance

Programming Notes with Unity

メニュー

[C#] クラスオブジェクトのディープコピー

C#のクラスオブジェクトをコピーしたい場合がまれによくある。
特にパラメータ系のクラスオブジェクトを作成して、元のオブジェクトの値は保持したままにして
渡した先であれこれしたい場合だ。

C#のクラスは参照での扱い方がベース(でありウリである所)なので、参照先で値をいじると元の方も変わってしまう。
それを避ける為には、元のクラスオブジェクトをコピーしたものを参照先に渡す必要がある。

C++ならmemcpyして終わりな問題でこれはこれでラクだったが、C#ではそうはいかない。
代わりに、浅いコピー(シャローコピー)深いコピー(ディープコピー)の2通りのコピー方法がある。

シャローコピーの方は簡単で、Objectクラスに元々MemberwiseCloneというメソッドがあり、
これを使って目的のクラスにキャストするだけだ。

ただし、MemberwiseCloneは文字通り浅いコピーであるという事に注意する必要がある。

もしクラス内に参照型の変数を持っている場合には、その参照先のクラスオブジェクトまでは複製されない。
あくまでも「参照先オブジェクトはこれです」という情報のみがコピーされるだけである。

もし参照型のメンバを持っているクラスの場合で、その参照先のオブジェクトも全て複製してコピーしたい場合を
ディープコピーと言うが、これを行うには自力で実装する必要がある。

こちらを参考にさせてもらって、汎用メソッド版と拡張メソッド版を以下のように用意した。

内容的には、BinaryFormatterによるシリアライズ、デシリアライズをMemoryStreamを介して行っているようなものか。
C#だとこの辺は少々めんどくさくなるが、致し方ない。

使用例はこんな感じ。


Unityでディープコピーを使用する際は、メンバ変数にMonoBehaviour継承のクラスといった
Unityで用意されている各コンポーネントクラスを持っている場合にはコピー出来ない(例外が発生する)ので注意。
(おそらくSystem.Serializable属性が指定されていない為と思われる。というかつけるわけがない・・・w)

参考:
http://smdn.jp/programming/netfx/cloning/
http://d.hatena.ne.jp/tekk/20091012/1255362429
http://d.hatena.ne.jp/tekk/20100131/1264913887

関連記事