假设我有一个类:
class obj
{
int a;
int b;
}
然后我有这段代码:
obj myobj = new obj(){ a=1, b=2}
obj myobj2 = myobj;
现在上面的代码引用了第一个对象。我的需求是让myobj2
引用一个myobj
的副本,而不会反映在原始对象中的更改。我已经在SO上搜索过,并且迄今为止的解决方案似乎很复杂。是否有更简单的方法来实现这一点。我正在使用.NET 4.5obj myobj2 = (obj)myobj.MemberwiseClone();
但在其他情况下,比如任何成员是引用类型,那么你需要进行深拷贝。你可以使用Serialization
和 Deserialization
技术结合 BinaryFormatter
类获取对象的深拷贝:
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
接口或使用内置属性(如OnDeserialized
、OnDeserializing
、OnSerializing
、OnSerialized
)来引入特殊的序列化和反序列化逻辑到我们的代码中。在所有情况下,StreamingContext
将作为参数传递给方法(对于ISerializable
接口的特殊构造函数也是如此)。通过将ContextState
设置为Clone
,我们只是向该方法“提示”序列化的目的。
附加信息:(您还可以从MSDN阅读本文)
浅复制是创建一个新对象,然后将当前对象的非静态字段复制到新对象中。如果字段是值类型,则执行字段的位拷贝;对于引用类型,复制引用但不复制所引用的对象;因此原始对象及其克隆体引用同一对象。
深复制是创建一个新对象,然后将当前对象的非静态字段复制到新对象中。如果字段是值类型,则执行字段的位拷贝。如果字段是引用类型,则执行所引用对象的新副本。[Serializable]
。 - NoWarobj myobj2 = (obj)myobj.MemberwiseClone();
该复制是浅复制,这意味着克隆对象中的引用属性指向与原始对象相同的值,但在您的情况下,这不应该成为问题,因为obj
中的属性是值类型。
如果您拥有源代码,还可以实现ICloneable
Object
上定义,因此存在于任何类/结构中。但是,该方法是“protected”。因此,如果您所在的类或派生自expression
类型,则可以调用expression.MemberwiseClone()
。例如,在上面的答案中,myobj
是表达式,它具有类型obj
,因此只能在类obj
内部或派生自obj
的类内部调用MemberwiseClone
。 - Jeppe Stig Nielsenobj
内部或者在从obj
派生出的类内部。 - Jeppe Stig Nielsen