Deep Copy of Object in C#

By FoxLearn 12/2/2024 8:05:29 AM   31
In C#, a deep copy of an object means creating a new instance of the object, along with all objects referenced by it, so that changes to the copy do not affect the original object, and vice versa.

Deep Copy of Object in C#?

One common method for deep copying objects is using serialization. This involves serializing the object into a memory stream and then deserializing it back into a new object, effectively creating a deep copy.

public static class ObjectCopier
{
    // Perform a deep copy of the object via serialization.
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", nameof(source));
        }

        // Don't serialize a null object, simply return the default for that object
        if (ReferenceEquals(source, null))
             return default;
        using var stream = new MemoryStream();
        IFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}

The method is generic, meaning it can work with any type T.

First, It creates a MemoryStream to temporarily store the serialized data, then use BinaryFormatter to serialize the object to the stream.

After serializing, it seeks to the beginning of the stream and deserializes the data back into a new object, which is a deep copy of the original.

var original = new Person { Name = "John", Address = new Address { Street = "123 Main St", City = "Somewhere" } };

// Deep copy the object
var copy = ObjectCopier.Clone(original);

// Modify the copy
copy.Name = "Jane";
copy.Address.City = "Anywhere";

// Print to verify changes
Console.WriteLine($"Original Name: {original.Name}, City: {original.Address.City}");
Console.WriteLine($"Copy Name: {copy.Name}, City: {copy.Address.City}");

The class of the object being copied must be marked as [Serializable] for this approach to work.

[Serializable]
public class Person
{
    public string Name { get; set; }
    public Address Address { get; set; }
}

[Serializable]
public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
}

This method uses BinaryFormatter, which is efficient but not recommended for new applications due to security concerns. Consider using other serializers like JsonSerializer for modern applications.

For example, Using JSON Serialization

public static T DeepCopy<T>(T obj)
{
    string json = JsonConvert.SerializeObject(obj);
    return JsonConvert.DeserializeObject<T>(json);
}

Another approach is to implement the ICloneable interface for the object you want to deep copy.

For example, Using Object Cloning (ICloneable Interface)

public class Person : ICloneable
{
    public string Name { get; set; }
    public Address Address { get; set; }

    public object Clone()
    {
        // Create a new Person object (shallow copy)
        var clone = (Person)this.MemberwiseClone();

        // Manually copy the reference type members
        clone.Address = new Address
        {
            Street = this.Address.Street,
            City = this.Address.City
        };
        return clone;
    }
}

Program.cs

var original = new Person
{
    Name = "John",
    Address = new Address { Street = "123 Main St", City = "Somewhere" }
};

// Deep copy of the object
var copy = (Person)original.Clone();

// Modify the copy
copy.Name = "Jane";
copy.Address.City = "Anywhere";

The best method depends on your specific use case, but serialization is a commonly used approach for deep copying in C#.