web-dev-qa-db-ja.com

C#でオブジェクトのコピーを作成する

可能な重複:
どのようにして.Netでオブジェクトをディープコピーするのですか(C#のみ)?

以下のコードを見てください(C#の本からの抜粋)。

namespace Example {
    class MyClass {
        public int val;
    }

    struct myStruct {
        public int val;
    }

    class Program {
        static void Main(string[] args) {
            MyClass objectA = new MyClass();
            MyClass objectB = objectA;
            objectA.val = 10;
            objectB.val = 20;
            myStruct structA = new myStruct();
            myStruct structB = structA;
            structA.val = 30;
            structB.val = 40;
            Console.WriteLine("objectA.val = {0}", objectA.val);
            Console.WriteLine("objectB.val = {0}", objectB.val);
            Console.WriteLine("structA.val = {0}", structA.val);
            Console.WriteLine("structB.val = {0}", structB.val);
            Console.ReadKey();
        }
    }
}

私はそれが以下の出力を生成することを理解しています

objectA.val = 20
objectB.val = 20
structA.val = 30
structB.val = 40

出力の最後の2行は問題ありませんが、最初の2行はobjectAobjectBが同じメモリブロックを参照していることを示しています(C#では、オブジェクトは参照型なので)。

問題は、objectBobjectAのコピーにして、メモリ内の別の領域を指すようにする方法です。メンバーを割り当てようとしても、それらのメンバーが参照になる可能性があるため、うまくいかない可能性があります。それでは、どのように私はobjectBobjectAと完全に異なる実体にすることについてどうすればいいですか?

ありがとう

139
afaolek

組み込みの方法はありません。あなたはMyClassにIClonableインターフェースを実装させることができます(しかしそれは一種の廃止予定です)、あるいはあなた自身のCopy/Cloneメソッドを書くだけです。どちらの場合でも、コードを書く必要があります。

大きなオブジェクトの場合は、既存のコードを再利用するためだけに、(MemoryStreamを使用して)シリアル化+逆シリアル化を検討できます。

どのような方法であれ、「コピー」が正確に何を意味するのかについて慎重に考えてください。いくら深くすればいいのでしょうか、除外するIdフィールドなどはありますか。

97
Henk Holterman

あなたがすることができます:

class myClass : ICloneable
{
    public String test;
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

それからあなたはできる

myClass a = new myClass();
myClass b = (myClass)a.Clone();

N.B. MemberwiseClone()現在のSystem.Objectの簡易コピーを作成します。

123
BugFinder

これを行う最も簡単な方法は、MyClassクラスにコピーコンストラクタを書くことです。

このようなもの:

namespace Example
{
    class MyClass
    {
        public int val;

        public MyClass()
        {
        }

        public MyClass(MyClass other)
        {
            val = other.val;
        }
    }
}

2番目のコンストラクタは、自分の型のパラメータ(コピーしたいもの)を単に受け入れて、同じ値を割り当てられた新しいオブジェクトを作成します。

class Program
{
    static void Main(string[] args)
    {
        MyClass objectA = new MyClass();
        MyClass objectB = new MyClass(objectA);
        objectA.val = 10;
        objectB.val = 20;
        Console.WriteLine("objectA.val = {0}", objectA.val);
        Console.WriteLine("objectB.val = {0}", objectB.val);
        Console.ReadKey();
    }
}

出力:

objectA.val = 10

objectB.val = 20               
44
Levi_vc

これについてはすでに質問があります、おそらくそれを読むことができます

ディープクローンオブジェクト

たとえばJavaにはClone()メソッドはありませんが、クラスにコピーコンストラクタを含めることができます。これは別の良い方法です。

class A
{
  private int attr

  public int Attr
  {
     get { return attr; }
     set { attr = value }
  }

  public A()
  {
  }

  public A(A p)
  {
     this.attr = p.Attr;
  }  
}

これは一例です。新しいオブジェクトを構築するときにメンバ 'Attr'をコピーします。

8
jgemedina