04 Dec 2023



Advanced

In the context of the Prototype Design Pattern in C#, shallow copy and deep copy refer to two different approaches when creating copies of objects. The Prototype Design Pattern involves creating new objects by copying an existing object, known as the prototype. The two types of copies, shallow and deep, differ in how they handle the object's internal references.

Shallow Copy:

  1. Definition:

    • A shallow copy creates a new object and copies the values of all fields to the new object.
    • If the fields are reference types, the references are copied, but not the actual objects they point to.
    • Changes to the fields of the shallow copy (especially reference types) will affect the original object.
  2. Code Example:

using System;

// Prototype interface
interface IPrototype
{
    IPrototype Clone(); // Method to create a clone of the prototype
}

// Concrete prototype
class ConcretePrototype : IPrototype
{
    public int Value { get; set; }
    public ReferenceType Reference { get; set; }

    // Shallow copy method
    public IPrototype Clone()
    {
        return (IPrototype)this.MemberwiseClone();
    }
}

class ReferenceType
{
    public int Data { get; set; }
}

class Program
{
    static void Main()
    {
        // Create an original object
        ConcretePrototype original = new ConcretePrototype
        {
            Value = 10,
            Reference = new ReferenceType { Data = 20 }
        };

        // Create a shallow copy of the original
        ConcretePrototype shallowCopy = (ConcretePrototype)original.Clone();

        // Display original and shallow copy values
        Console.WriteLine($"Original Value: {original.Value}, Original Reference Data: {original.Reference.Data}");
        Console.WriteLine($"Shallow Copy Value: {shallowCopy.Value}, Shallow Copy Reference Data: {shallowCopy.Reference.Data}");

        // Modify the shallow copy's value and reference data
        shallowCopy.Value = 5;
        shallowCopy.Reference.Data = 15;

        // Changes in the shallow copy affect the original's reference data
        Console.WriteLine($"Original Reference Data after Shallow Copy Modification: {original.Reference.Data}");
    }
}

Explanation for Shallow Copy:

  • The ConcretePrototype class implements the IPrototype interface, defining a Clone method for shallow copying using MemberwiseClone().
  • The ReferenceType class is a reference type within the ConcretePrototype.
  • In the Main method, an original object is created, and a shallow copy is made using the Clone method.
  • Changes to the shallow copy affect the original's reference data because they share the same reference.
  • Effect: Both original and shallowCopy reference the same objects if there are any reference-type fields.
  • Outcome: Changes to the fields of the shallow copy (especially reference types) will affect the original object.

Deep Copy:

  • Definition:

    • A deep copy creates a new object and recursively creates copies of all objects referenced by the original object.
    • Ensures that the copied object is entirely independent of the original, including its referenced objects.
    • Changes to the fields of the deep copy will not affect the original object, as it creates independent copies of referenced objects.
  • Code Example:

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

// Prototype interface
interface IPrototype
{
    IPrototype Clone(); // Method to create a clone of the prototype
}

// Concrete prototype
[Serializable]
class ConcretePrototype : IPrototype
{
    public int Value { get; set; }
    public ReferenceType Reference { get; set; }

    // Deep copy method using serialization
    public IPrototype Clone()
    {
        return DeepCopy(this);
    }

    // Helper method for deep copy using serialization
    private static T DeepCopy<T>(T obj)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            IFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memoryStream, obj);
            memoryStream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(memoryStream);
        }
    }
}

class ReferenceType
{
    public int Data { get; set; }
}

class Program
{
    static void Main()
    {
        // Create an original object
        ConcretePrototype original = new ConcretePrototype
        {
            Value = 10,
            Reference = new ReferenceType { Data = 20 }
        };

        // Create a deep copy of the original
        ConcretePrototype deepCopy = (ConcretePrototype)original.Clone();

        // Display original and deep copy values
        Console.WriteLine($"Original Value: {original.Value}, Original Reference Data: {original.Reference.Data}");
        Console.WriteLine($"Deep Copy Value: {deepCopy.Value}, Deep Copy Reference Data: {deepCopy.Reference.Data}");

        // Modify the deep copy's value and reference data
        deepCopy.Value = 5;
        deepCopy.Reference.Data = 15;

        // Changes in the deep copy do not affect the original's reference data
        Console.WriteLine($"Original Reference Data after Deep Copy Modification: {original.Reference.Data}");
    }
}

Explanation for Deep Copy:

  • The ConcretePrototype class now implements the IPrototype interface with a Clone method that calls a DeepCopy helper method.
  • The DeepCopy method uses serialization to create a deep copy of the object and its referenced objects.
  • In the Main method, an original object is created, and a deep copy is made using the Clone method.
  • Changes to the deep copy do not affect the original's reference data because they are independent copies.
  • Effect:
    • deepCopy is entirely independent of original, and changes to one do not affect the other.
  • Outcome: Changes to the fields of the deep copy will not affect the original object, as it creates independent copies of referenced objects.

In both examples, the Clone method is implemented in the ConcretePrototype class to provide a mechanism for creating copies. The deep copy method uses serialization to create a deep, independent copy of the object and its referenced objects.

software-design-patterns
prototype-design-pattern
shallow-copy
deep-copy
c#