Shallow Copy and Deep Copy in C#

Shallow Copy and Deep Copy in C# with Examples

In this article, I will discuss the Shallow Copy and Deep Copy in C# with Examples. Please read our previous article discussing Prototype Design Patterns in C# with Examples. Shallow Copy and Deep Copy play important roles in copying the objects in the Prototype Design Pattern. So, in this article, we will discuss Shallow Copy and Deep Copy and the differences between them with examples.

Understanding Shallow Copy in C#:

In the case of Shallow copy, it will create the new object from the existing object and then copy the value type fields of the current object to the new object. But in the case of reference type, it will only copy the reference, not the referred object itself. Therefore, the original and clone refer to the same object in the case of reference type. To understand this better, please have a look at the following diagram. As you can see in the below image, we are having Employee and Address classes.

Further, you notice inside the Employee class, we have declared two value-type properties, i.e., Name and Department, and one reference-type property, i.e., EmpAddress. In the case of Shallow Copy, the value of the value type properties will be cloned while the reference address of the reference type will be cloned into the new object. With Shall Copy in C#, both existing and cloned objects will point to the same memory location in the case of reference type property.

Understanding Shallow Copy in C#

As shown in the above diagram, first, we create an object, i.e., emp1, and then initialize the object with some values. Then, we create the second object, i.e., emp2, using the GetClone method. The memory representation shows that the value type fields (Name and Department) are copied and stored in a different memory location. In contrast, the reference type field, i.e., EmpAddress, still points to the same old memory location. That means both emp1 and emp2 now refer to the same Address object. So, if we make any changes to the employee address, they will affect each other.

Example to Understand Shallow Copy in C#:

The following Example shows the use of Shallow Copy in C#. The following Example code is self-explained, so please go through the comment lines for a better understanding.

using System;
namespace ShallowCopyDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Example to Understand Shallow Copy
            //Creating Employee Object
            Employee emp1 = new Employee
            {
                Name = "Anurag",
                Department = "IT",
                EmpAddress = new Address() { address = "BBSR" }
            };

            //Creating a Clone Object from the Existing Object
            Employee emp2 = emp1.GetClone();

            //Changing Name Property of Clone Object Will Not Reflect the Existing Object
            emp2.Name = "Pranaya";

            //Changing Address Property of Clone Object Will Reflect the Changes of the Existing Object
            //This is because address is a reference type property and in the case of Shallow Copy
            //Both Clone and Existing Object will point to the Same Memory Address
            emp2.EmpAddress.address = "Mumbai";

            Console.WriteLine("Emplpyee 1: ");
            Console.WriteLine("Name: " + emp1.Name + ", Address: " + emp1.EmpAddress.address + ", Dept: " + emp1.Department);
            Console.WriteLine("Emplpyee 2: ");
            Console.WriteLine("Name: " + emp2.Name + ", Address: " + emp2.EmpAddress.address + ", Dept: " + emp2.Department);

            Console.Read();
        }
    }

    public class Employee
    {
        //Value type Property
        public string Name { get; set; }
        //Value type Property
        public string Department { get; set; }
        //Reference type Property
        public Address EmpAddress { get; set; }

        //Creating a Cloned Object of the Current Object
        public Employee GetClone()
        {
            //Both Cloned and Existing Object Point to the Same Memory Location of the Address Object
            return (Employee)this.MemberwiseClone();
        }
    }

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

In the above code, after creating the second employee object, i.e., the cloned employee, we are changing the address and name of the second employee, i.e., emp2. Now, when you run the application, you will see that the address is changed for the emp1 also, as shown in the below image.

Example to Understand Shallow Copy in C#

Note: In C#, the term “shallow copy” refers to a method of copying an object where only the references to the objects are copied and not the actual objects themselves. If the original object contains references to other objects (like arrays or class objects), then in a shallow copy, both the original and the copy will refer to the same objects.

When to use Shallow Copy in C#?

Shallow copy is useful in certain scenarios where sharing references between the original and copied objects is acceptable or desirable. Here are some situations where you might want to use a shallow copy in C#:

  • Performance Concerns: Shallow copies are generally faster than deep copies because they only involve copying references rather than duplicating entire objects. If performance is a concern and shared references aren’t problematic, you might choose shallow copying.
  • Memory Efficiency: If the copied objects are large or contain large nested objects, making deep copies could quickly consume a significant amount of memory. Shallow copying avoids this by sharing references.
  • Shared State: If you want multiple objects to have a shared state through some of their properties, shallow copying can be a way to achieve this. Changes in the shared state (reference) will be reflected across all objects that hold that reference.
  • Temporary Duplicate: A shallow copy might suffice if you need a temporary duplicate of an object (maybe for some transient calculations or operations) and you’re sure you won’t be altering shared state inappropriately.
  • Prototyping and Design Patterns: In some design patterns, like the Prototype pattern, a shallow copy might be used when the pattern implementation does not require completely independent clones.
  • Immutable Inner Objects: If the inner objects of the main object are immutable (i.e., they can’t be changed after they’re created), then shallow copying is safe because those inner objects can’t be modified anyway.
  • Array Cloning: When you use the Clone() method on an array in C#, it performs a shallow copy. This might be all you need if the array elements are value types or immutable reference types.
Understanding Deep Copy in C#:

In the case of deep copy, it will create a new object from the existing object and then copy the fields of the current object to the newly created object. If the field is a value type, then a bit-by-bit copy of the field will be performed. A new copy of the referred object will be created if the field is a reference type. For a better understanding, please have a look at the following image. This is the same example that we discussed with the Shallow Copy. But here, you can see, we have implemented the GetClone method in both Employee and Address classes. From the Employee class GetClone method, we call the Address class GetClone method. This is how we can implement Deep Copy in C#.

Understanding Deep Copy in C#

As shown in the above image, the Name and Department properties are value types, so it creates a copy of that and stores it in a different location. The EmpAddress is a Reference type property, and in Deep Copy, there is a clone of the reference type field, which will be stored in a different location. So, the point that you need to remember is that in the case of Deep Copy, the field type does not matter whether it is a value or reference type. It always makes a copy of the whole data and stores it in a different memory location. 

Example to Understand Deep Copy in C#:

The following Example shows the use of Deep Copy in C#. The following Example code is self-explained, so please go through the comment lines for a better understanding.

using System;
namespace DeepCopyDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Example to Understand Deep Copy
            //Creating Employee Object
            Employee emp1 = new Employee
            {
                Name = "Anurag",
                Department = "IT",
                EmpAddress = new Address() { address = "BBSR" }
            };

            //Creating a Clone Object from the Existing Object
            Employee emp2 = emp1.GetClone();

            //Changing Name Property of Clone Object Will Not Reflect the Existing Object
            emp2.Name = "Pranaya";

            //Changing Address Property of Clone Object Will Not Reflect the Changes in the Existing Object
            //This is because of Deep Copy
            //Both Clone and Existing Object have Memory locations for the Address object
            emp2.EmpAddress.address = "Mumbai";

            Console.WriteLine("Emplpyee 1: ");
            Console.WriteLine("Name: " + emp1.Name + ", Address: " + emp1.EmpAddress.address + ", Dept: " + emp1.Department);
            Console.WriteLine("Emplpyee 2: ");
            Console.WriteLine("Name: " + emp2.Name + ", Address: " + emp2.EmpAddress.address + ", Dept: " + emp2.Department);

            Console.Read();
        }
    }

    public class Employee
    {
        //Value type Property
        public string Name { get; set; }
        //Value type Property
        public string Department { get; set; }
        //Reference type Property
        public Address EmpAddress { get; set; }

        //Creating a Cloned Object of the Current Object
        public Employee GetClone()
        {
            Employee employee = (Employee)this.MemberwiseClone();
            //The following Statement will make this a Deep Copy
            //Now, Cloned and Existing Object have different Memory Locations for the Address Object
            employee.EmpAddress = EmpAddress.GetClone();
            return employee;
        }
    }

    public class Address
    {
        public string address { get; set; }
        //Creating a Cloned Object of the Current Object
        public Address GetClone()
        {
            return (Address)this.MemberwiseClone();
        }
    }
}
Output:

Example to Understand Deep Copy in C#

Note: In C#, a “deep copy” means recursively creating a new object that is a copy of the original object along with all the objects inside it. This way, changes to the new object won’t affect the original object or vice versa. To perform a deep copy, you typically have to manually copy each field of the object, taking care to also deep copy any reference types.

When to use Deep Copy in C#?

Using a deep copy ensures that the original and copied objects are entirely independent, meaning changes to one will not affect the other. Here are some scenarios where a deep copy is appropriate or even necessary in C#:

  • Complete Independence: A deep copy is the way to go if you want two objects to operate independently, without any shared state. This is especially important if modifications to one object shouldn’t reflect on the other.
  • Undo/Redo Functionality: Deep copying is essential to preserve the states independently in applications where you need to maintain a history of object states for undo/redo operations (like graphic editors or word processors).
  • Cloning Objects in Design Patterns: In certain design patterns, like the Prototype pattern, a deep copy is needed if you want each clone to be a distinct object with no shared references.
  • Avoiding Side Effects: When passing objects to methods, especially in multi-threaded environments, deep copies can prevent unintended side effects caused by multiple threads accessing and modifying the same reference.
  • Serialization: Serialization processes often inherently create deep copies of objects. When you serialize an object to a format (e.g., to JSON or XML) and then deserialize it, you get a deep copy of the original object.
  • Data Isolation: In certain scenarios, like simulations or testing, where you must run the same process on an unchanged data set repeatedly, deep copying ensures the data remains consistent across runs.
  • Security and Data Integrity: Deep copying can prevent unintentional data leaks or modifications if you’re working with sensitive data. By working with a deep copy, you can ensure that the original data remains untouched.
  • Temporary Object Alteration: If you need to create a temporary object based on an existing one, make changes without affecting the original, and perhaps discard it after use, deep copying is appropriate.
  • Network Communications: When sending objects across a network, you might want to work with a deep copy to ensure that the original object remains untouched and consistent during communication.
  • Avoiding Circular References: In scenarios where objects have circular references (A refers to B, and B refers back to A), deep copying (when done correctly) can manage and preserve such structures without infinite loops.
Differences Between Shallow Copy and Deep Copy in C#:

Shallow Copy and Deep Copy create a Clone Object from an Existing Object. The difference between them is that, in the case of Shallow copy, it will create the clone object from the existing object and then copy the value type fields of the existing object to the new object. But for the reference type property, it will only copy the reference, not the actual object itself. Therefore, the existing and cloned objects refer to the same memory location in the case of reference type.

On the other hand, in the case of Deep Copy, it will create the clone object from the existing object and then copy the fields of the existing object to the newly created clone object. If the field is a value type, then a bit-by-bit copy of the field will be performed. A new copy of the referred object will be created if the field is a reference type. Unlike the Shallow Copy, in the case of Deep Copy, both existing and clone objects have different memory locations for the reference type properties.

So, according to the application requirement, you must decide whether to use Shallow Copy or Deep Copy, even though you can declare two methods within the class. One method is for Shallow Copy, and another method is for Deep Copy. For a better understanding, please have a look at the following example. Here, within the Employee class, we have two methods. The GetShallowCopy method will do a Shallow Copy of the clone object, and the GetDeepCopy method will do a deep copy of the clone object.

using System;
namespace ShallowCopyDeepCopyDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Example to Understand Deep Copy and Shallow Copy in C#
            //Creating Employee Object
            Employee emp1 = new Employee
            {
                Name = "Anurag",
                Department = "IT",
                EmpAddress = new Address() { address = "BBSR" }
            };

            //Creating a Clone Object from the Existing Object using the GetDeepCopy method
            Employee emp2 = emp1.GetDeepCopy();

            //Changing Name and Address Property of Clone Object
            emp2.Name = "Pranaya";
            emp2.EmpAddress.address = "Mumbai";

            Console.WriteLine("Using Deep Copy");
            Console.WriteLine($" Emplpyee 1: Name: {emp1.Name}, Address: {emp1.EmpAddress.address}");
            Console.WriteLine($" Emplpyee 2: Name: {emp2.Name}, Address: {emp2.EmpAddress.address}");

            //Creating Employee Object
            Employee emp3 = new Employee
            {
                Name = "Sambit",
                Department = "HR",
                EmpAddress = new Address() { address = "Delhi" }
            };

            //Creating a Clone Object from the Existing Object using the GetShallowCopy method
            Employee emp4 = emp3.GetShallowCopy();

            //Changing Name and Address Property of Clone Object
            emp4.Name = "Hina";
            emp4.EmpAddress.address = "Hyderabad";

            Console.WriteLine("\nUsing Shallow Copy");
            Console.WriteLine($" Emplpyee 3: Name: {emp3.Name}, Address: {emp3.EmpAddress.address}");
            Console.WriteLine($" Emplpyee 4: Name: {emp4.Name}, Address: {emp4.EmpAddress.address}");
            
            Console.Read();
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public string Department { get; set; }
        public Address EmpAddress { get; set; }

        //Creating a Clone Object of the Current Object using Shallow Copy
        public Employee GetShallowCopy()
        {
            Employee employee = (Employee)this.MemberwiseClone();
            return employee;
        }

        //Creating a Clone Object of the Current Object using Deep Copy
        public Employee GetDeepCopy()
        {
            Employee employee = (Employee)this.MemberwiseClone();
            employee.EmpAddress = EmpAddress.GetClone();
            return employee;
        }
    }

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

Differences Between Shallow Copy and Deep Copy in C#

Both shallow and deep copies in C# pertain to replicating an object, but they differ in the depth of that replication. Here’s a detailed breakdown of their differences:

Definition:
  • Shallow Copy: Creates a new object and inserts references from the original object into the new object. If the original object has reference fields, the references (not the actual objects) are copied, meaning both the original and its copy refer to the same objects.
  • Deep Copy: Creates a new object and recursively copies value and reference fields from the original object. This means the original and its copy are entirely separate; changes in one won’t affect the other.
Reference Types:
  • Shallow Copy: Reference types inside the original object remain shared between the original and the copied object.
  • Deep Copy: Each reference type in the original is also deeply copied. The copied object gets its own instances of each reference type.
Modification Effects:
  • Shallow Copy: Modifying a reference type inside the copied object will also modify the same data in the original object since they share the same reference.
  • Deep Copy: Modifications in the copied object won’t affect the original object, and vice versa, as they are completely independent of each other.
Implementation:
  • Shallow Copy: This can often be achieved with methods like MemberwiseClone() in C# for classes.
  • Deep Copy: Requires custom code to recursively copy inner objects or use serialization-deserialization methods as a workaround.
Performance:
  • Shallow Copy: Generally faster since it only involves copying references.
  • Deep Copy: This can be slower, especially for large objects or objects with deep hierarchies, since every part of the object needs to be recreated.
Use Cases:
  • Shallow Copy: Useful when you want to create a copy with shared inner objects or when deep copying is unnecessary.
  • Deep Copy: Essential when you want two objects to be entirely independent, such as in undo-redo functionality or when cloning objects in certain design patterns.
Limitations:
  • Shallow Copy: This can lead to unintended side effects if one is not careful, as modifications in the copied object’s reference types reflect in the original.
  • Deep Copy: More complex to implement, especially for objects with intricate structures or when objects have circular references.

In summary, the choice between shallow and deep copy depends on the specific requirements of your application. If you want completely independent objects, opt for a deep copy. If shared references are acceptable or desirable, a shallow copy may suffice.

In the next article, I will discuss Real-Time Examples of the Prototype Design Pattern in C#. In this article, I try to explain the Shallow Copy and Deep Copy in C# with Examples. I hope you enjoy this Shallow Copy and Deep Copy in C# article.

1 thought on “Shallow Copy and Deep Copy in C#”

Leave a Reply

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