Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Shallow and Deep Object Copying

, 1 May 2009
Rate this:
Please Sign up or sign in to vote.
In .NET, class objects are reference types. Assigning one object variable to another object variable does not copy that object, it simply causes both object variables to reference the same object. Sometimes, a copy is required. For example, maybe two routines need to start with the same data but th

In .NET, class objects are reference types. Assigning one object variable to another object variable does not copy that object, it simply causes both object variables to reference the same object.

Sometimes, a copy is required. For example, maybe two routines need to start with the same data but then change that data independently from each other. Copying the data ensures that changes made by one routine will not impact the data being used by the other routine.

When using .NET, two types of copies are possible: shallow and deep. In the case of a shallow copy, a new object is created and each member from the original object is assigned to the corresponding member of the new object. In the case of value members, this is a copy in the truest sense. However, with objects that contain reference members, this does not produce a true copy.

One example of a reference type is a string. When you assign one string variable to another, both variables will reference the same string data. The characters of the strings are not truly copied. So if a class contains reference members, a shallow copy does not create a true copy of all class members.

For many cases, a shallow copy is sufficient. Note that strings are immutable and cannot be changed. When you create a shallow copy of an object that contains strings, and then modify a string in the new object, that would create a new string and would not have any impact on the original string in the original object. Note that other data types such as arrays, class objects, and arrays of class objects can be quite a bit more complicated than strings.

A deep copy is when a copy is created that contains none of the original data. A true copy of each member is created. A deep copy doesn’t need to do anything special with members that are value types. But for reference data types, the new object must reference copies of that data instead of the original data.

There is nothing unique about how either method of copying an object are performed. Consider listing 1. This code declares a class called MyClass, and then shows a short method called Test that performs both a shallow and a deep copy using that class object.

protected class MyClass
{
   public int i;
   public int j;
   public string message;
}
private void Test()
{
   MyClass mc1;
   MyClass mc2;
   mc1 = new MyClass();
   mc1.i = 5;
   mc1.j = 10;
   mc1.message = "Hello, World!";

   // Shallow copy
   mc2 = new MyClass();
   mc2.i = mc1.i;
   mc2.j = mc1.j;
   mc2.message = mc1.message;

   // Deep copy
   mc2 = new MyClass();
   mc2.i = mc1.i;
   mc2.j = mc1.j;
   mc2.message = String.Copy(mc1.message);
}

Listing 1: Shallow and deep copying of an object.

The shallow copy does nothing special. It simply assigns each member from one object to the other. For value members, the deep copy uses the same code. However, for the one reference member, message, the code must create a copy of the string data. (Note that addition steps would be required to perform a deep copy with objects that include reference members with references to additional objects, such as class members, arrays, etc.)

Now that I’ve hopefully explained the difference between a shallow and a deep copy, let’s take a look at some of the tools the .NET frameworks provide to perform these tasks.

protected class MyClass : ICloneable
{
    public int i;
    public int j;
    public string message;
    public object Clone()
    {
        return MemberwiseClone();
    }
}

private void Test()
{
    MyClass mc1 = new MyClass();
    mc1.i = 5;
    mc1.j = 10;
    mc1.message = "Hello, World!";

    // Shallow copy
    MyClass mc2 = (MyClass)mc1.Clone();
}

Listing 2: Using MemberwiseClone() to perform a shallow copy.

Listing 2 uses MemberwiseClone() to perform a shallow copy. MemberwiseClone() is protected and so cannot be called directly from Test. Instead, I’ve modified MyClass to implement the ICloneable interface and implemented the one ICloneable method, Clone. (Normally, ICloneable is associated with a deep copy but I use it here to implement a shallow copy.) The Test method calls this new method to perform the shallow copy. Since Clone() returns type object, a type cast is required.

To perform a deep copy, Listing 3 also implements the ICloneable interface. This listing just modifies the code in the Clone() method to perform a deep copy.

protected class MyClass : ICloneable
{
    public int i;
    public int j;
    public string message;
    public object Clone()
    {
        MyClass mc = new MyClass();
        mc.i = i;
        mc.j = j;
        if (message != null)
            mc.message = String.Copy(message);
        return mc;
    }
}

private void Test()
{
    MyClass mc1 = new MyClass();
    mc1.i = 5;
    mc1.j = 10;
    mc1.message = "Hello, World!";

    // Deep copy
    MyClass mc2 = (MyClass)mc1.Clone();
}

Listing 3: Using ICloneable to perform a deep copy.

The actual code in the Clone() method should be familiar by now. The main advantage to implementing it this way is that it is implemented as part of the class, where it can easily be modified and called from any where in your application.

Nothing too complex here, although the concept behind a shallow and deep copy can be confusing to some. Hopefully, I’ve shown some light on this topic and demonstrated how you might approach the issue using .NET.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Jonathan Wood
Black Belt Coder
United States United States
Jonathan Wood has been a software developer for more years than he cares to admit. His current focus is on using C# and ASP.NET MVC to develop website applications, and C++ and MFC to develop desktop applications. His consulting company, SoftCircuits, is known for producing various commercial and shareware products.
 
Having an entrepreneurial spirit, Jonathan also has a number of other online businesses that he built from scratch such as Black Belt Coder, Trail Calendar and others. He also has expertise in designing brands (including graphics and logos) and search-engine optimization (SEO).
 
Jonathan is always willing to discuss consulting work or joint ventures with people looking to develop software or online businesses.
Follow on   Twitter

Comments and Discussions

 
GeneralThanks.... PinmemberRick Hansen5-May-09 4:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 1 May 2009
Article Copyright 2009 by Jonathan Wood
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid