在C#中创建对象的副本

时间:2011-07-04 09:21:24

标签: c# object reference cloning

  

可能重复:
  How do you do a deep copy an object in .Net (C# specifically)?

请查看下面的代码(摘自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

输出的最后两行我没有问题,但前两行告诉我objectAobjectB指向同一个内存块(因为在C#中,对象是引用类型)。

问题是如何制作objectB objectA的副本,以便它指向内存中的不同区域。我理解,尝试分配他们的成员可能不起作用,因为这些成员也可能是参考。那么如何让objectB成为与objectA完全不同的实体呢?

由于

4 个答案:

答案 0 :(得分:123)

你可以这样做:

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的浅表副本。

答案 1 :(得分:97)

没有内置方式。你可以让MyClass实现IClonable接口(但它有点被弃用)或者只是编写自己的Copy / Clone方法。在任何一种情况下,您都必须编写一些代码。

对于大对象,您可以考虑序列化+反序列化(通过MemoryStream),只是为了重用现有代码。

无论采用何种方法,都要仔细考虑“副本”的含义。它应该有多深,是否有Id字段除外等。

答案 2 :(得分:43)

最简单的方法是在MyClass类中编写一个复制构造函数。

这样的事情:

namespace Example
{
    class MyClass
    {
        public int val;

        public MyClass()
        {
        }

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

第二个构造函数只接受他自己类型的参数(你要复制的参数)并创建一个分配了相同值的新对象

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               

答案 3 :(得分:7)

已经有一个关于此的问题,你或许可以阅读它

Deep cloning objects

例如,Java中没有Clone()方法,但你可以在你的clases中包含一个复制构造函数,这是另一个好方法。

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'。