Deep cloning objects

Viewed 948913

I want to do something like:

MyObject myObj = GetMyObj(); // Create and fill a new object
MyObject newObj = myObj.Clone();

And then make changes to the new object that are not reflected in the original object.

I don't often need this functionality, so when it's been necessary, I've resorted to creating a new object and then copying each property individually, but it always leaves me with the feeling that there is a better or more elegant way of handling the situation.

How can I clone or deep copy an object so that the cloned object can be modified without any changes being reflected in the original object?

58 Answers

Whereas one approach is to implement the ICloneable interface (described here, so I won't regurgitate), here's a nice deep clone object copier I found on The Code Project a while ago and incorporated it into our code. As mentioned elsewhere, it requires your objects to be serializable.

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

/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
    /// <summary>
    /// Perform a deep copy of the object via serialization.
    /// </summary>
    /// <typeparam name="T">The type of object being copied.</typeparam>
    /// <param name="source">The object instance to copy.</param>
    /// <returns>A deep copy of the object.</returns>
    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 stream = new MemoryStream();
        IFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}

The idea is that it serializes your object and then deserializes it into a fresh object. The benefit is that you don't have to concern yourself about cloning everything when an object gets too complex.

In case of you prefer to use the new extension methods of C# 3.0, change the method to have the following signature:

public static T Clone<T>(this T source)
{
   // ...
}

Now the method call simply becomes objectBeingCloned.Clone();.

EDIT (January 10 2015) Thought I'd revisit this, to mention I recently started using (Newtonsoft) Json to do this, it should be lighter, and avoids the overhead of [Serializable] tags. (NB @atconway has pointed out in the comments that private members are not cloned using the JSON method)

/// <summary>
/// Perform a deep Copy of the object, using Json as a serialization method. NOTE: Private members are not cloned using this method.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneJson<T>(this T source)
{            
    // Don't serialize a null object, simply return the default for that object
    if (ReferenceEquals(source, null)) return default;

    // initialize inner objects individually
    // for example in default constructor some list property initialized with some values,
    // but in 'source' these items are cleaned -
    // without ObjectCreationHandling.Replace default constructor values will be added to result
    var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};

    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}

The reason not to use ICloneable is not because it doesn't have a generic interface. The reason not to use it is because it's vague. It doesn't make clear whether you're getting a shallow or a deep copy; that's up to the implementer.

Yes, MemberwiseClone makes a shallow copy, but the opposite of MemberwiseClone isn't Clone; it would be, perhaps, DeepClone, which doesn't exist. When you use an object through its ICloneable interface, you can't know which kind of cloning the underlying object performs. (And XML comments won't make it clear, because you'll get the interface comments rather than the ones on the object's Clone method.)

What I usually do is simply make a Copy method that does exactly what I want.

I prefer a copy constructor to a clone. The intent is clearer.

The short answer is you inherit from the ICloneable interface and then implement the .clone function. Clone should do a memberwise copy and perform a deep copy on any member that requires it, then return the resulting object. This is a recursive operation ( it requires that all members of the class you want to clone are either value types or implement ICloneable and that their members are either value types or implement ICloneable, and so on).

For a more detailed explanation on Cloning using ICloneable, check out this article.

The long answer is "it depends". As mentioned by others, ICloneable is not supported by generics, requires special considerations for circular class references, and is actually viewed by some as a "mistake" in the .NET Framework. The serialization method depends on your objects being serializable, which they may not be and you may have no control over. There is still much debate in the community over which is the "best" practice. In reality, none of the solutions are the one-size fits all best practice for all situations like ICloneable was originally interpreted to be.

See the this Developer's Corner article for a few more options (credit to Ian).

  1. Basically you need to implement ICloneable interface and then realize object structure copying.
  2. If it's deep copy of all members, you need to insure (not relating on solution you choose) that all children are clonable as well.
  3. Sometimes you need to be aware of some restriction during this process, for example if you copying the ORM objects most of frameworks allow only one object attached to the session and you MUST NOT make clones of this object, or if it's possible you need to care about session attaching of these objects.

Cheers.

DeepCloner: Quick, easy, effective NuGet package to solve cloning

After reading all answers I was surprised no one mentioned this excellent package:

DeepCloner GitHub project

DeepCloner NuGet package

Elaborating a bit on its README, here are the reason why we chose it at work:

  • It can deep or shallow copy
  • In deep cloning all object graph is maintained.
  • Uses code-generation in runtime, as result cloning is blazingly fast
  • Objects copied by internal structure, no methods or ctors called
  • You don't need to mark classes somehow (like Serializable-attribute, or implement interfaces)
  • No requirement to specify object type for cloning. Object can be casted to interface or as an abstract object (e.g. you can clone array of ints as abstract Array or IEnumerable; even null can be cloned without any errors)
  • Cloned object doesn't have any ability to determine that he is clone (except with very specific methods)

Usage:

var deepClone = new { Id = 1, Name = "222" }.DeepClone();
var shallowClone = new { Id = 1, Name = "222" }.ShallowClone();

Performance:

The README contains a performance comparison of various cloning libraries and methods: DeepCloner Performance.

Requirements:

  • .NET 4.0 or higher or .NET Standard 1.3 (.NET Core)
  • Requires Full Trust permission set or Reflection permission (MemberAccess)

In general, you implement the ICloneable interface and implement Clone yourself. C# objects have a built-in MemberwiseClone method that performs a shallow copy that can help you out for all the primitives.

For a deep copy, there is no way it can know how to automatically do it.

Disclaimer: I'm the author of the mentioned package.

I was surprised how the top answers to this question in 2019 still use serialization or reflection.

Serialization is limiting (requires attributes, specific constructors, etc.) and is very slow

BinaryFormatter requires the Serializable attribute, JsonConverter requires a parameterless constructor or attributes, neither handle read only fields or interfaces very well and both are 10-30x slower than necessary.

Expression Trees

You can instead use Expression Trees or Reflection.Emit to generate cloning code only once, then use that compiled code instead of slow reflection or serialization.

Having come across the problem myself and seeing no satisfactory solution, I decided to create a package that does just that and works with every type and is a almost as fast as custom written code.

You can find the project on GitHub: https://github.com/marcelltoth/ObjectCloner

Usage

You can install it from NuGet. Either get the ObjectCloner package and use it as:

var clone = ObjectCloner.DeepClone(original);

or if you don't mind polluting your object type with extensions get ObjectCloner.Extensions as well and write:

var clone = original.DeepClone();

Performance

A simple benchmark of cloning a class hierarchy showed performance ~3x faster than using Reflection, ~12x faster than Newtonsoft.Json serialization and ~36x faster than the highly suggested BinaryFormatter.

Create an extension:

public static T Clone<T>(this T theObject)
{
    string jsonData = JsonConvert.SerializeObject(theObject);
    return JsonConvert.DeserializeObject<T>(jsonData);
}

And call it like this:

NewObject = OldObject.Clone();

As nearly all of the answers to this question have been unsatisfactory or plainly don't work in my situation, I have authored AnyClone which is entirely implemented with reflection and solved all of the needs here. I was unable to get serialization to work in a complicated scenario with complex structure, and IClonable is less than ideal - in fact it shouldn't even be necessary.

Standard ignore attributes are supported using [IgnoreDataMember], [NonSerialized]. Supports complex collections, properties without setters, readonly fields etc.

I hope it helps someone else out there who ran into the same problems I did.

C# 9.0 is introducing the with keyword that requires a record (Thanks Mark Nading). This should allow very simple object cloning (and mutation if required) with very little boilerplate, but only with a record.

You cannot seem to be able to clone (by value) a class by putting it into a generic record;

using System;
                
public class Program
{
    public class Example
    {
        public string A { get; set; }
    }
    
    public record ClonerRecord<T>(T a)
    {
    }

    public static void Main()
    {
        var foo = new Example {A = "Hello World"};
        var bar = (new ClonerRecord<Example>(foo) with {}).a;
        foo.A = "Goodbye World :(";
        Console.WriteLine(bar.A);
    }
}

This writes "Goodbye World :("- the string was copied by reference (undesired). https://dotnetfiddle.net/w3IJgG

(Incredibly, the above works correctly with a struct! https://dotnetfiddle.net/469NJv)

But cloning a record does seem to work as indented, cloning by value.

using System;

public class Program
{
    public record Example
    {
        public string A { get; set; }
    }
    
    public static void Main()
    {
        var foo = new Example {A = "Hello World"};
        var bar = foo with {};
        foo.A = "Goodbye World :(";
        Console.WriteLine(bar.A);
    }
}

This returns "Hello World", the string was copied by value! https://dotnetfiddle.net/MCHGEL

More information can be found on the blog post:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/with-expression

Shortest way but need dependency:

using Newtonsoft.Json;
    public static T Clone<T>(T source) =>
        JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));

The generic approaches are all technically valid, but I just wanted to add a note from myself since we rarely actually need a real deep copy, and I would strongly oppose using generic deep copying in actual business applications since that makes it so you might have many places where the objects are copied and then modified explicitly, its easy to get lost.

In most real-life situations also you want to have as much granular control over the copying process as possible since you are not only coupled to the data access framework but also in practice the copied business objects should rarely be 100% the same. Think an example referenceId's used by the ORM to identify object references, a full deep copy will also copy this id's so while in-memory the objects will be different, as soon as you submit it to the datastore, it will complain, so you will have to modify this properties manually after copying anyway and if the object changes you need to adjust it in all of the places which use the generic deep copying.

Expanding on @cregox answer with ICloneable, what actually is a deep copy? Its just a newly allocated object on the heap that is identical to the original object but occupies a different memory space, as such rather than using a generic cloner functionality why not just create a new object?

I personally use the idea of static factory methods on my domain objects.

Example:

    public class Client
    {
        public string Name { get; set; }

        protected Client()
        {
        }

        public static Client Clone(Client copiedClient)
        {
            return new Client
            {
                Name = copiedClient.Name
            };
        }
    }

    public class Shop
    {
        public string Name { get; set; }

        public string Address { get; set; }

        public ICollection<Client> Clients { get; set; }

        public static Shop Clone(Shop copiedShop, string newAddress, ICollection<Client> clients)
        {
            var copiedClients = new List<Client>();
            foreach (var client in copiedShop.Clients)
            {
                copiedClients.Add(Client.Clone(client));
            }

            return new Shop
            {
                Name = copiedShop.Name,
                Address = newAddress,
                Clients = copiedClients
            };
        }
    }

If someone is looking how he can structure object instantiation while retaining full control over the copying process that's a solution that I have been personally very successful with. The protected constructors also make it so, other developers are forced to use the factory methods which gives a neat single point of object instantiation encapsulating the construction logic inside of the object. You can also overload the method and have several clone logic's for different places if necessary.

Deep cloning is about copying state. For .net state means fields.

Let's say one have an hierarchy:

static class RandomHelper
{
    private static readonly Random random = new Random();

    public static int Next(int maxValue) => random.Next(maxValue);
}

class A
{
    private readonly int random = RandomHelper.Next(100);

    public override string ToString() => $"{typeof(A).Name}.{nameof(random)} = {random}";
}

class B : A
{
    private readonly int random = RandomHelper.Next(100);

    public override string ToString() => $"{typeof(B).Name}.{nameof(random)} = {random} {base.ToString()}";
}

class C : B
{
    private readonly int random = RandomHelper.Next(100);

    public override string ToString() => $"{typeof(C).Name}.{nameof(random)} = {random} {base.ToString()}";
}

Cloning can be done:

static class DeepCloneExtension
{
    // consider instance fields, both public and non-public
    private static readonly BindingFlags bindingFlags =
        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

    public static T DeepClone<T>(this T obj) where T : new()
    {
        var type = obj.GetType();
        var result = (T)Activator.CreateInstance(type);

        do
            // copy all fields
            foreach (var field in type.GetFields(bindingFlags))
                field.SetValue(result, field.GetValue(obj));
        // for every level of hierarchy
        while ((type = type.BaseType) != typeof(object));

        return result;
    }
}

Demo1:

Console.WriteLine(new C());
Console.WriteLine(new C());

var c = new C();
Console.WriteLine($"{Environment.NewLine}Image: {c}{Environment.NewLine}");

Console.WriteLine(new C());
Console.WriteLine(new C());

Console.WriteLine($"{Environment.NewLine}Clone: {c.DeepClone()}{Environment.NewLine}");

Console.WriteLine(new C());
Console.WriteLine(new C());

Result:

C.random = 92 B.random = 66 A.random = 71
C.random = 36 B.random = 64 A.random = 17

Image: C.random = 96 B.random = 18 A.random = 46

C.random = 60 B.random = 7 A.random = 37
C.random = 78 B.random = 11 A.random = 18

Clone: C.random = 96 B.random = 18 A.random = 46

C.random = 33 B.random = 63 A.random = 38
C.random = 4 B.random = 5 A.random = 79

Notice, all new objects have random values for random field, but clone exactly matches the image

Demo2:

class D
{
    public event EventHandler Event;
    public void RaiseEvent() => Event?.Invoke(this, EventArgs.Empty);
}

// ...

var image = new D();
Console.WriteLine($"Created obj #{image.GetHashCode()}");

image.Event += (sender, e) => Console.WriteLine($"Event from obj #{sender.GetHashCode()}");
Console.WriteLine($"Subscribed to event of obj #{image.GetHashCode()}");

image.RaiseEvent();
image.RaiseEvent();

var clone = image.DeepClone();
Console.WriteLine($"obj #{image.GetHashCode()} cloned to obj #{clone.GetHashCode()}");

clone.RaiseEvent();
image.RaiseEvent();

Result:

Created obj #46104728
Subscribed to event of obj #46104728
Event from obj #46104728
Event from obj #46104728
obj #46104728 cloned to obj #12289376
Event from obj #12289376
Event from obj #46104728

Notice, event backing field is copied too and client is subscribed to clone's event too.

I’ll use the below simple way to implement this. Just create an abstract class and implement method to serialize and deserialize again and return.

public abstract class CloneablePrototype<T>
{
    public T DeepCopy()
    {
        string result = JsonConvert.SerializeObject(this);
        return JsonConvert.DeserializeObject<T>(result);
    }
}
public class YourClass : CloneablePrototype< YourClass>
…
…
…

And the use it like this to create deep copy.

YourClass newObj = (YourClass)oldObj.DeepCopy();

This solution is easy to extend as well if you need to implement the shallow copy method as well.

Just implement a new method in the abstract class.

public T ShallowCopy()
{
    return (T)this.MemberwiseClone();
}

Besides some of the brilliant answers here, what you can do in C# 9.0 & higher, is the following (assuming you can convert your class to a record):

record Record
{
    public int Property1 { get; set; }

    public string Property2 { get; set; }
}

And then, simply use with operator to copy values of one object to the new one.

var object1 = new Record()
{
    Property1 = 1,
    Property2 = "2"
};

var object2 = object1 with { };
// object2 now has Property1 = 1 & Property2 = "2"

I hope this helps :)

C# Extension that'll support for "not ISerializable" types too.

 public static class AppExtensions
 {                                                                      
       public static T DeepClone<T>(this T a)
       {
           using (var stream = new MemoryStream())
           {
               var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));

               serializer.Serialize(stream, a);
               stream.Position = 0;
               return (T)serializer.Deserialize(stream);
           }
       }                                                                    
 }

Usage

       var obj2 = obj1.DeepClone()

Using System.Text.Json:

https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/

public static T DeepCopy<T>(this T source)
{
    return source == null ? default : JsonSerializer.Parse<T>(JsonSerializer.ToString(source));
}

The new API is using Span<T>. This should be fast, would be nice to do some benchmarks.

Note: there's no need for ObjectCreationHandling.Replace like in Json.NET as it will replace collection values by default. You should forget about Json.NET now as everything is going to be replaced with the new official API.

I'm not sure this will work with private fields.

using System.Text.Json;

public static class CloneExtensions
{
    public static T Clone<T>(this T cloneable) where T : new()
    {
        var toJson = JsonSerializer.Serialize(cloneable);
        return JsonSerializer.Deserialize<T>(toJson);
    }
}

I did some benchmark on current answers and found some interesting facts.

Using BinarySerializer => https://stackoverflow.com/a/78612/6338072

Using XmlSerializer => https://stackoverflow.com/a/50150204/6338072

Using Activator.CreateInstance => https://stackoverflow.com/a/56691124/6338072

These are the results

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.18363.1734 (1909/November2019Update/19H2)

Intel Core i5-6200U CPU 2.30GHz (Skylake), 1 CPU, 4 logical and 2 physical cores [Host] : .NET Framework 4.8 (4.8.4400.0), X86 LegacyJIT DefaultJob : .NET Framework 4.8 (4.8.4400.0), X86 LegacyJIT

Method Mean Error StdDev Gen 0 Allocated
BinarySerializer 220.69 us 4.374 us 9.963 us 49.8047 77 KB
XmlSerializer 182.72 us 3.619 us 9.405 us 21.9727 34 KB
Activator.CreateInstance 49.99 us 0.992 us 2.861 us 1.9531 3 KB

In the codebase I am working with, we had a copy of the file ObjectExtensions.cs from the GitHub project Burtsev-Alexey/net-object-deep-copy. It is 9 years old. It worked, although we later realized it was very slow for larger object structures.

Instead, we found a fork of the file ObjectExtensions.cs in the GitHub project jpmikkers/Baksteen.Extensions.DeepCopy. A deep copy operation of a large data structure that previously took us about 30 minutes, now feels almost instantaneous.

This improved version has the following documentation:

C# extension method for fast object cloning.

This is a speed-optimized fork of Alexey Burtsev's deep copier. Depending on your usecase, this will be 2x - 3x faster than the original. It also fixes some bugs which are present in the original code. Compared to the classic binary serialization/deserialization deep clone technique, this version is about seven times faster (the more arrays your objects contain, the bigger the speedup factor).

The speedup is achieved via the following techniques:

  • object reflection results are cached
  • don't deep copy primitives or immutable structs & classes (e.g. enum and string)
  • to improve locality of reference, process the 'fast' dimensions or multidimensional arrays in the inner loops
  • use a compiled lamba expression to call MemberwiseClone

How to use:

using Baksteen.Extensions.DeepCopy;
...
var myobject = new SomeClass();
...
var myclone = myobject.DeepCopy()!;    // creates a new deep copy of the original object 

Note: the exclamation mark (null-forgiving operator) is only required if you enabled nullable referency types in your project

For the cloning process, the object can be converted to the byte array first and then converted back to the object.

public static class Extentions
{
    public static T Clone<T>(this T obj)
    {
        byte[] buffer = BinarySerialize(obj);
        return (T)BinaryDeserialize(buffer);
    }

    public static byte[] BinarySerialize(object obj)
    {
        using (var stream = new MemoryStream())
        {
            var formatter = new BinaryFormatter(); 
            formatter.Serialize(stream, obj); 
            return stream.ToArray();
        }
    }

    public static object BinaryDeserialize(byte[] buffer)
    {
        using (var stream = new MemoryStream(buffer))
        {
           var formatter = new BinaryFormatter(); 
           return formatter.Deserialize(stream);
        }
    }
}

The object must be serialized for the serialization process.

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

Usage:

MyObject myObj  = GetMyObj();
MyObject newObj = myObj.Clone();

An addition to @Konrad and @craastad with using built in System.Text.Json for .NET >5

https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?pivots=dotnet-5-0

Method:

public static T Clone<T>(T source)
{
    var serialized = JsonSerializer.Serialize(source);
    return JsonSerializer.Deserialize<T>(serialized);
}

Extension method:

public static class SystemExtension
{
    public static T Clone<T>(this T source)
    {
        var serialized = JsonSerializer.Serialize(source);
        return JsonSerializer.Deserialize<T>(serialized);
    }
}

Building upon @craastad's answer, for derived classes.

In the original answer, if the caller is calling DeepCopy on a base class object, the cloned object is of a base class. But the following code will return the derived class.

using Newtonsoft.Json;

public static T DeepCopy<T>(this T source)
{
    return (T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), source.GetType());
}

If you use net.core and the object is serializable, you can use

var jsonBin = BinaryData.FromObjectAsJson(yourObject);

then

var yourObjectCloned = jsonBin.ToObjectFromJson<YourType>();

BinaryData is in dotnet therefore you don't need a third party lib. It also can handle the situation that the property on your class is Object type (the actual data in your property still need to be serializable)

Related