如何在c#中创建对象的副本

本文关键字:创建对象 副本 | 更新日期: 2023-09-27 18:14:57

假设我有一个类:

class obj
{
  int a;
  int b;
}

然后我有这个代码:

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

现在上面的代码引用了第一个对象。我想要的是,myobj2指的是myobj的副本,其更改没有反映在原始版本中。我已经搜索了SO,到目前为止的解决方案似乎很复杂。有更简单的方法吗?我使用的是。net 4.5

如何在c#中创建对象的副本

对象中的属性是值类型,您可以在这样的情况下使用浅复制:

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

但在其他情况下,比如任何成员都是引用类型,则需要深度复制。您可以在BinaryFormatter类的帮助下使用SerializationDeserialization技术获得对象的深度副本:

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接口或使用内置属性(如OnDeserializedOnDeserializingOnSerializingOnSerialized),在代码中引入特殊的序列化和反序列化逻辑。在所有情况下,StreamingContext都将作为参数传递给方法(在ISerializable接口的情况下传递给特殊的构造函数)。通过将ContextState设置为Clone,我们只是给该方法一个关于序列化目的的提示

附加信息:(你也可以从MSDN阅读这篇文章)

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

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

可以使用MemberwiseClone

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

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

如果您拥有源代码,您也可以实现iclonable