Deep and Shallow Copy in C#

08 November 2021 at 10:00 by ParTech Media - Post a comment

When we use C# to copy one instance to another, both instances end up with the same memory address. However, most of the time, this is not the behavior we desire.

When we create a copy of an object, for example MyClass obj=new MyClass(); MyClass obj2=obj. The '=' operator then copies the reference rather than the object (and it works fine for a Value Type).

The MemberwiseClone() function in the superclass System is used by default to achieve this behavior. This is referred to as "Shallow Copy".

We use the Clone() method from the System.ICloneable interface to get the same behavior for a Reference Type and a Value Type. This is referred to as a "Deep Copy."

In this post, we will deep dive into both these techniques with the help of examples.

Table of contents

  1. What is a Shallow copy in C#?
  2. Example of Shallow Copy
  3. What is Deep copy in C#?
  4. Example of Deep Copy
  5. Difference between Shallow copy and Deep copy
  6. Conclusion

What is a Shallow Copy in C#?

Shallow copying involves establishing a new object and then copying the existing object's non-static fields to the new object. A bit-by-bit duplicate of the field is performed if it is a value type. Since the reference is copied but the referred object is not, the original object and its clone refer to the same object.

A shallow copy of an object is a new object with the same instance variables as the original. The object function MemberwiseClone() in.Net performs shallow copying.

If you have an object with values and you want to make a copy of it in another variable of the same type, then you can use a shallow copy. All property values of value types will be copied, but if you have a property of reference type, you will just have a reference to that instance.

Example of Shallow Copy

A shallow copy creates a new object from an existing object and then copies the value type fields from the existing object to the new one. The reference type, on the other hand, will only duplicate the reference, not the referred object itself. In the case of reference type, the original and clone refer to the same object. Take a look at the program below to get a better understanding.

using Sytem;
namespace PrototypeDesignPattern
{
class Test
{
static void Main(string[] args)
{
Employees empl = new Employees();
empl.Emp_Name = “Ruud”;
empl.Emp_Department = “IT”;
empl.Emp_Address = new EmpAddess() { address = “Amsterdam”};

Employees emp2 = empl.GetClone();
emp2.Emp_Name = “Okke”;
emp2.Emp_Address.address = “Rotterdam”;

Console.WriteLine (“Employee 1: ”); 
Console.WriteLine (“Name: ” + empl.Emp_Name +	 “, Address: ”
emp1.Emp_Address.address + “, Dept: ” + emp1.Emp_Department);

Console.WriteLine (“Employee 2: ”); 
Console.WriteLine (“Name: ” + emp2.Emp_Name + “, Address: ”
emp2.Emp_Address.address + “, Dept: ” + emp2.Emp_Department);

Console.Read();
}
}

public class Employees
{
public string Emp_name {get; set;}
public string Emp_Department {get;	set;}
public EmpAddress Emp_Address {get; set;}

public Employees GetClone()
{
return (Employees)this.MenberwiseClone();
}

public class EmpAddress
{
public string address {get; set;}
}
}

As you can see from the above program, we first construct an object emp1 and then set values to it. The GetClone function is then used to create the second object, emp2.

The value type fields (Emp_Name and Emp_Department) are copied and placed in a different memory address, as shown in the memory representation, while the reference type field (Emp_Address) still points to the same old memory location.

This means - both the objects, emp1 and emp2, now relate to the same Address object. As a result, any changes to the employee address will have an impact on the other.

Now we will update the address and name of the second employee, emp2, in the above code after establishing the second employee object.

When you start the application now, you'll notice that the address for the emp1 has also been modified, as shown in the image below.

Output:

Employee 1:

Name: Ruud, Address: Amsterdam, Dept: IT

Employee 2:

Name: Okke, Address: Rotterdam, Dept: IT

What is Deep Copy in C#?

Deep copy is the process of generating a new object and then copying the existing object's non-static fields to the new object. A bit-by-bit duplicate of the field is performed if it is a value type. A fresh copy of the referred object is created if a field is of the reference type.

A deep duplicate of an object is a completely new object with all-new instance variables; it does not share any objects with the original. The classes to be cloned must be marked as [Serializable] while executing Deep Copy.

Deep copy copies all of an object's elements, including directly referenced value type elements and indirectly referred reference type elements that hold a reference to a memory location containing data (rather than containing the data itself).

Example of Deep Copy

A deep copy will generate a new object from an existing object and then copy the fields from the old object to the newly produced object. A bit-by-bit duplicate of the field will be performed if the field has a value type. A new copy of the referred object is produced if the field is a reference type.

using Sytem;
namespace PrototypeDesignPattern
{
class Test1
{
static void Main(string[] args)
{
Employees emp_l = new Employees();
emp_l.Emp_Name = “Ruud”;
emp_l.Emp_Department = “IT”;
emp_l.Emp_Address = new Addess() { address = “Amsterdam”};

Employees emp_2 = emp_l.GetClone();
emp_2.Emp_Name = “Okke”;
emp_2.Emp_Address.address = “Rotterdam”;

Console.WriteLine (“Employee 1: ”); 
Console.WriteLine (“Name: ” + emp_l.Emp_Name + “, Address: ”
emp_1.Emp_Address.address + “, Department: ” + emp_1.Emp_Department);

Console.WriteLine (“Employee 2: ”); 
Console.WriteLine (“Name: ” + emp_2.Emp_Name + “, Address: ”
emp_2.Emp_Address.address + “, Dept: ” + emp_2.Emp_Department);

Console.Read();
}
}

public class Employees
{
public string Emp_name {get; set;}
public string Emp_Department {get;	set;}
public Address Emp_Address {get; set;}

public Employees GetClone()
{
Employees employee = (Employees)this.MemberwiseClone();
employee.Emp_Address = Emp_Address.GetClone();
return employee;
}

public class Address
{
public string address {get; set;}
Public Address GetClone()
{
return (Address)this.MemberwiseClone();
}
}
}

Because the Emp_Name and Emp_Department attributes in the previous program are value types, it copies them and saves them in a new location. The Emp_Address property is of the Reference type, and there is a clone of the reference type field in Deep Copy, which will likewise be stored in a separate location. The important point to remember here is that the field type does not matter whether it is a value type or a reference type when using Deep Copy. It always copies the entire data set and saves it in a separate memory address.

Output:

Employee 1:

Name: Ruud, Address: Amsterdam, Dept: IT

Employee 2:

Name: Okke, Address: Rotterdam, Dept: IT

Summary of differences between Shallow copy and Deep copy

Shallow Copy

  1. It is the process of constructing a new collection object and then populating it with references
  2. It does not recurse and it does not create copies of the child objects themselves to the child objects found in the original.
  3. It is not recursive.

Deep Copy

  1. It is the process of constructing a new collection object and then recursively populating it with copies of the child object found in the original.
  2. It creates a complete independent clone of the original and all of its children.
  3. It is recursive.

Final Words

Both Deep Copy and Shallow Copy have their own positives and negatives. You need to pick a technique depending upon the need of your program. Both the techniques are also unique in their own way as far as the syntax is concerned. So go ahead and pick one of them for your next application.

Latest