关于.net:如何在c#中制作对象的副本

How to make a copy of an object in c#

本问题已经有最佳答案,请猛点这里访问。

假设我有一个班级:

1
2
3
4
5
class obj
{
  int a;
  int b;
}

然后我有了这个代码:

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

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


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

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

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

1
2
3
4
5
6
7
8
9
10
11
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

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

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

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