There are two ways to copy an object: Shallow and Deep.

A shallow copy of an object copies all the member variables bit by bit if the member field is a value type. For reference types, the reference is copied but the referred object is not. This means that both the original objects and its clone refer to the same object.

In contrast, a deep copy of an object copies everything directly or indirectly referenced by the object. Consider an object called X that references object A and B. Object B, in turn, references object C. A deep copy of X creates a new object X2 that references the new objects A2 and B2. B2, in turn, references the new object C2. Needless to say that A2, B2 and C2 are copies of the A, B and C objects respectively. On the other hand, a shallow copy of X creates a new X2 that references objects A and B.

So what’s the shallow copy of an Array? How is it different from the deep copy of the same array?

Anyhow, the real question is that how to make the shallow copy of an object in .NET framework? Well, actually you don’t need to do too much. All you have to do is to call the protected MemberwiseClone on an object. However, the framework doesn’t support the deep copy counterpart operation and therefore it should be done manually. The following simple example illustrates you how to do so.

using System;
using System.Diagnostics;

class ClassX
{
    public Int32 a;
    public ClassB b;

    public ClassX ShallowCopy()
    {
        return (ClassX)this.MemberwiseClone();
    }

    public ClassX DeepCopy()
    {
        ClassX copy = new ClassX();
        copy.a = this.a;
        copy.b = this.b.DeepCopy();

        return copy;
    }
}

class ClassB
{
    public Int32 i;

    public ClassB DeepCopy()
    {
        ClassB copy = new ClassB();
        copy.i = this.i;
        return copy;
    }
}

static class Program
{
    static void Main()
    {
        ClassX x = new ClassX();
        x.a = 1;
        x.b = new ClassB();
        x.b.i = 2;

        ClassX shallowCopy = x.ShallowCopy();

        x.b.i = 3; //change the orginal object
        Trace.WriteLine("(reference type) - the copy is also changed to: " + shallowCopy.b.i);

        x.a = 4; //change the orginal object
        Trace.WriteLine("(value type) - the copy is still: " + shallowCopy.a);

        ClassX deepCopy = x.DeepCopy();
        x.b.i = 5; //change the orginal object
        Trace.WriteLine("(reference type) - the copy is still: " + deepCopy.b.i);

        x.a = 6; //change the orginal object
        Trace.WriteLine("(value type) - the copy is still: " + deepCopy.a);
    }
}

(For those who are familiar with C++, we’ve to do the same thing using the copy constructor and the assignment operator.)

As the above-mentioned example shows, we’ve to make a copy of each member manually. This is really annoying when your class has got too many member fields. That is where the Binary Serialization comes into play. However, you’ve to be really careful when using this technique since it will degrade the application performance.

First, you’ve to decorate the classes ClassX and ClassB with the Serializable attribute. Then, replace the body of the ClassX.DeepCopy method with the following code. You’ve also add the System.Runtime.Serialization.Formatters.Soap.dll assembly to the application references.

public ClassX DeepCopy()
{
    using (MemoryStream stream = new MemoryStream())
    {
        BinaryFormatter fmt = new BinaryFormatter();
        fmt.Serialize(stream, this);
        stream.Seek(0, SeekOrigin.Begin);
        return (ClassX)fmt.Deserialize(stream);
    }
}

That’s all for now folks.

 

One Response to Shallow Copy vs Deep Copy

  1. ConstReader says:

    Real Good work.
    Thank you 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Tweets

Rubber horse attack? Seriously? It's Rubber hose dudes! #security #fail

Sponsors