ここから本文です

C#でオブジェクトのコピーはどうするのでしょう

ichimanniさん

2011/3/516:35:23

C#でオブジェクトのコピーはどうするのでしょう

たとえば
Bitmap a = new Bitmap()
Bitmap b;
として、aのビットマップを

b = a;

としても、aの内容を書き換えたら、bも一緒に変わっちゃいますよね

閲覧数:
58,238
回答数:
2

違反報告

ベストアンサーに選ばれた回答

abiko_tetuさん

編集あり2011/3/615:13:09

[値を複写する型と複写しない型の違い]

下記は御存知かも知れませんが、話しの手順として、まず、一緒に変わる場合の条件と、変わらない条件の違いを説明します。
その後に、本題の回答をします。


値型の場合は、代入演算子「 = 」により、値が渡されます(値型については、後述)。
これに対して、参照型の場合は、代入演算子「 = 」により、メモリ上で値が格納されている場所のアドレスが渡されます(参照型については、後述)。
よって、値型ならば、代入元(質問での a )の値が書き替えられても、代入先(質問での b )の値は変わりません。
しかし、参照型の場合は、代入元( a )の値が書き替えられたら、代入先( b )の値も一緒に変わります。メモリ上は、同じ保存場所なのですから。

ここで値型とは、int型、float型、bool型 等の、オブジェクトの生成の際に、new を使わないタイプの型のことです。
これに対して、参照型とは、上記以外の物で、主にクラスのことを指しています。
質問のBitmap は、クラスなので、代入元( a )の値が書き替えられたら、代入先( b )の値も一緒に変わります。





[用意されているクラスの場合]

質問には、「たとえば」とあるので、Bitmap だけに限らない質問だと思います。
Bitmap クラスでは、複写用にClone()メソッドが用意されていますが、Bitmap 以外のクラスでも、基本的に複写用メソッドは、Clone()メソッドになっています。
よって、Bitmap クラスに限らず、使用しようとしているクラスに、Clone()と言うメソッドが有るのか調べて下さい。
もしも該当クラスにClone()メソッドが無い場合は、複写する処理を自分で考えなければならないので、大変になるかも知れません(そのケースの場合では、再質問を出して、良い方法は無いのか、意見を聞かれたらどうでしょうか)





[自分で作るクラスの場合]

自分で作るクラスの場合では、そのクラスにClone()メソッドを定義する必要があります。
もちろん、自分でメソッドの名前を決めても良いのですが、基本的には、Clone()と言うメソッド名にして下さい。
下記にDataClassと言う自作クラスに、Clone()メソッドを実装する場合のコード例を示します。
なお、下記の ICloneable は、Clone()メソッド用のインターフェイス(interface)です。
もしも、インターフェイスをまだ使われたことが無い場合は、ICloneable の意味は、取り合えず「自分で作ったクラスに、Clone()メソッドを実装しましたよ」と言う宣言のような物と捉えて下さい。



public class DataClass : ICloneable
{

public int data1;
public int data2;
public int data3;

public object Clone()
{
DataClass work = new DataClass();
work.data1 = this.data1;
work.data2 = this.data2;
work.data3 = this.data3;
return work;
}

}





上記クラスの使い方の例は、以下となります。




DataClass a = new DataClass();
a.data1 = 7;
a.data2 = 8;
a.data3 = 9;

DataClass b = (DataClass)a.Clone();
a.data2 = 12; // 代入元を書き換え





[MemberwiseClone()メソッドの利用]

なお、上記コード例のClone()メソッドの定義は、MemberwiseClone()と言うメソッドを使えば、もっと簡単に書けます。
以下のように。


public object Clone()
{
return MemberwiseClone();
}



ただし、上記のMemberwiseClone()メソッドの利用は、メンバー変数の型が値型に限ります。
もしも、参照型のメンバーがあれば、そのメンバーは、メモリ上でのアドレスが渡されてしまいます(前述の元と先とが、一緒に変わるパターン)。
よって、参照型のメンバーがある場合で、詳細までコピーしたい場合は、最初のコード例のように、ひとつひとつのメンバーを、値で複写する処理を記述して下さい。





[簡易コピーと詳細コピー]

ICloneable.Clone メソッドの説明を見てみましょう。

http://msdn.microsoft.com/ja-jp/library/system.icloneable.clone(VS....

引用
Clone は、詳細コピーまたは簡易コピーとして実装できます。詳細コピーの場合は、すべてのオブジェクトが複製されますが、簡易コピーの場合は、最上位オブジェクトだけが複製され、下位のオブジェクトには参照が格納されます。


なお、上記までの説明は、該当クラスの直接のメンバーのコピーしか考慮していませんので、引用文で言うところの簡易コピーになります。
詳細コピーでは、直接のメンバーの、さらに下位層のメンバーのコピーまで考慮しなければなりません。





[自作クラスの詳細コピーの定義]

詳細コピー(下位層までのコピー)は、私は使う機会が無かったのですが、興味がありましたので、調べてサンプルを作ってみました。
しかし、回答量上限の制限で、もう書けませんので、もしも必要でしたら再質問を出して下さい。

この質問は投票によってベストアンサーに選ばれました!

ベストアンサー以外の回答

1〜1件/1件中

xianren428さん

2011/3/516:56:58

オブジェクトの設計しだいでしょう。
.NET の Bitmap の場合は Clone メソッドを使います。

あわせて知りたい

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問や知恵ノートは選択されたID/ニックネームのMy知恵袋で確認できます。