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.

链接地址: http://www.djcxy.com/p/40750.html

上一篇: 解密可串行结构不起作用

下一篇: 在C#中进行深度复制