Deep Copy in C#
MSDN gives this example of a deep copy (http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx)
public class Person
{
public int Age;
public string Name;
public IdInfo IdInfo;
public Person ShallowCopy()
{
return (Person)this.MemberwiseClone();
}
public Person DeepCopy()
{
Person other = (Person) this.MemberwiseClone();
other.IdInfo = new IdInfo(this.IdInfo.IdNumber);
return other;
}
}
But, doesn't a new Person object have to be instantiated, and then returned? For example, is this code below acceptable/equal/inferior to the code above for performing a deep copy?
As I understand the MemberwiseClone() method, it just performs a shallow copy, ie copies values/references from copied object to new object. This results in a shallow copy since the memory references are equal, ie the references point to the same objects.
public class Person
{
public int Age;
public string Name;
public IdInfo IdInfo;
public Person ShallowCopy()
{
return (Person)this.MemberwiseClone();
}
public Person DeepCopy()
{
Person other = new Person(); // difference
other.IdInfo = new IdInfo(this.IdInfo.IdNumber);
return other;
}
}
In the example that you specified, the values of Age and Name would be zero/blank.
This is due to the fact that you instantiate the Person object, but never set the values of these fields.
From Object.MemberwiseClone Method
The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.
So as you can see, using the MemberwiseClone method, your Age/Name fields will also be copied/cloned.
Alternatively, if you are able to set Serializable
attribute to all involved classes, you can use serialization. For the purpose of a generic deep copy I have this object
extension method:
public static class ObjectExtensions
{
#region Methods
public static T Copy<T>(this T source)
{
var isNotSerializable = !typeof(T).IsSerializable;
if (isNotSerializable)
throw new ArgumentException("The type must be serializable.", "source");
var sourceIsNull = ReferenceEquals(source, null);
if (sourceIsNull)
return default(T);
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
#endregion
}
This should also copy your IdInfo
field.
Usage is simple:
var copy = obj.Copy();
The MemberwiseClone()
creates a new instance of the class being copied, and also copies scalar fields into the corresponding members of the copy. It provides a better starting point for deep copying than just a plain new
, because you need to "fix" only the items requiring deep copying.
上一篇: 解密可串行结构不起作用
下一篇: 在C#中进行深度复制