在C#中创建一个对象的副本

请看一下下面的代码(摘自C#书)。

public class MyClass 
{
    public int val;
}
public struct myStruct 
{
    public int val;
}
public class Program 
{
    private 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完全不同的实体呢?

谢谢

你可以这样做。

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

评论(6)
解决办法

没有内置的方法。你可以让MyClass实现IClonable接口(但它已经被废弃了),或者直接写你自己的复制/克隆方法。无论哪种情况,你都必须写一些代码。

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

不管用什么方法,都要仔细考虑"复制"的确切含义。它应该深入到什么程度,是否有Id字段要被排除等等。

评论(6)

已经有一个关于这个问题的问题,你也许可以读一读。

https://stackoverflow.com/questions/78536/cloning-objects-in-c

例如,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'。

评论(0)