如何在c#中制作对象的副本

时间:2013-05-22 15:59:22

标签: c# .net clone

假设我有一个班级:

class obj
{
  int a;
  int b;
}

然后我有了这段代码:

obj myobj = new obj(){ a=1, b=2}
obj myobj2 = myobj;

现在上面的代码引用了第一个obj。我想要的是myobj2指的是myobj的副本,其中的更改未反映在原文中。我搜索了SO,到目前为止解决方案似乎很复杂。有没有更简单的方法来做到这一点。我正在使用.net 4.5

2 个答案:

答案 0 :(得分:81)

对象中的属性是值类型,您可以在以下情况下使用浅表副本:

obj myobj2 = (obj)myobj.MemberwiseClone();

但在其他情况下,如果有任何成员是引用类型,那么您需要Deep Copy。您可以在Serialization类的帮助下使用DeserializationBinaryFormatter技术获取对象的深层副本:

public static T DeepCopy<T>(T other)
{
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Context = new StreamingContext(StreamingContextStates.Clone);
        formatter.Serialize(ms, other);
        ms.Position = 0;
        return (T)formatter.Deserialize(ms);
    }
}

设置StreamingContext的目的: 我们可以在我们的代码中引入特殊的序列化和反序列化逻辑,帮助实现ISerializable接口或使用内置属性,如OnDeserializedOnDeserializingOnSerializing,{{ 1}}。在所有情况下,OnSerialized将作为参数传递给方法(如果是StreamingContext接口,则传递给特殊构造函数)。将ISerializable设置为ContextState后,我们只是为该方法提供有关序列化目的的提示

其他信息:(您还可以阅读MSDN中的这篇文章)

浅层复制正在创建一个新对象,然后将当前对象的非静态字段复制到新对象。如果字段是值类型,则执行字段的逐位复制;对于引用类型,引用被复制但引用的对象不是;因此原始对象及其克隆引用相同的对象。

深层复制正在创建一个新对象,然后将当前对象的非静态字段复制到新对象。如果字段是值类型,则执行字段的逐位复制。如果字段是引用类型,则执行引用对象的新副本。

答案 1 :(得分:4)

您可以使用MemberwiseClone

obj myobj2 = (obj)myobj.MemberwiseClone();

副本是浅拷贝,这意味着克隆中的引用属性指向与原始对象相同的值,但在您的情况下这不应该是一个问题,因为obj中的属性是有价值的类型。

如果您拥有源代码,则还可以实现ICloneable