Categories
.net c# clone

Deep cloning objects

2513

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?

12

  • 101

    May be useful: “Why Copying an Object is a terrible thing to do?” agiledeveloper.com/articles/cloning072002.htm

    – Pedro77

    Dec 7, 2011 at 11:56

  • 1

    stackoverflow.com/questions/8025890/… Another solution…

    – Felix K.

    Mar 16, 2012 at 16:39

  • 23

    You should have a look at AutoMapper

    Dec 19, 2012 at 0:36

  • 3

    Your solution is far more complex, I got lost reading it… hehehe. I’m using an DeepClone interface. public interface IDeepCloneable<T> { T DeepClone(); }

    – Pedro77

    Aug 9, 2013 at 14:12

  • 3

    @Pedro77 — Though, interestingly, that article ends up saying to create a clone method on the class, then have it call an internal, private constructor that gets passed this. So copying is turrible [sic], but copying carefully (and the article’s definitely worth reading) isn’t. ;^)

    – ruffin

    Sep 5, 2014 at 16:54

1866

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);
}

25

  • 27

    stackoverflow.com/questions/78536/cloning-objects-in-c/… has a link to the code above [and references two other such implementations, one of which is more appropriate in my context]

    Feb 4, 2009 at 13:13

  • 114

    Serialization/deserialization involves significant overhead that isn’t necessary. See the ICloneable interface and .MemberWise() clone methods in C#.

    – 3Dave

    Jan 28, 2010 at 17:28

  • 21

    @David, granted, but if the objects are light, and the performance hit when using it is not too high for your requirements, then it is a useful tip. I haven’t used it intensively with large amounts of data in a loop, I admit, but I have never seen a single performance concern.

    – johnc

    Jan 29, 2010 at 0:21


  • 18

    @Amir: actually, no: typeof(T).IsSerializable is also true if the type has been marked with the [Serializable] attribute. It doesn’t have to implement the ISerializable interface.

    Jun 3, 2011 at 15:25

  • 12

    Just thought I’d mention that whilst this method is useful, and I’ve used it myself many a time, it’s not at all compatible with Medium Trust – so watch out if you’re writing code that needs compatibility. BinaryFormatter access private fields and thus cannot work in the default permissionset for partial trust environments. You could try another serializer, but make sure your caller knows that the clone may not be perfect if the incoming object relies on private fields.

    Oct 17, 2011 at 11:35


383

I wanted a cloner for very simple objects of mostly primitives and lists. If your object is out of the box JSON serializable then this method will do the trick. This requires no modification or implementation of interfaces on the cloned class, just a JSON serializer like JSON.NET.

public static T Clone<T>(T source)
{
    var serialized = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(serialized);
}

Also, you can use this extension method

public static class SystemExtension
{
    public static T Clone<T>(this T source)
    {
        var serialized = JsonConvert.SerializeObject(source);
        return JsonConvert.DeserializeObject<T>(serialized);
    }
}

11

  • 17

    the solutiojn is even faster than the BinaryFormatter solution, .NET Serialization Performance Comparison

    – esskar

    Mar 12, 2014 at 10:25


  • 3

    Thanks for this. I was able to do essentially the same thing with the BSON serializer that ships with the MongoDB driver for C#.

    – Mark Ewer

    Jun 18, 2014 at 0:58

  • 5

    This is the best way for me, However, I use Newtonsoft.Json.JsonConvert but it is the same

    – Pierre

    Feb 4, 2015 at 12:20

  • 2

    For this to work the object to clone needs to be serializable as already mentioned – this also means for example that it may not have circular dependencies

    – radomeit

    Feb 22, 2018 at 10:03


  • 3

    I think this is the best solution as the implementation can be applied on most programming languages.

    – mr5

    Jan 2, 2019 at 7:58

192

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.

4

  • I’m not clear why ICloneable is considered vague. Given a type like Dictionary(Of T,U), I would expect that ICloneable.Clone should do whatever level of deep and shallow copying is necessary to make the new dictionary be an independent dictionary that contains the same T’s and U’s (struct contents, and/or object references) as the original. Where’s the ambiguity? To be sure, a generic ICloneable(Of T), which inherited ISelf(Of T), which included a “Self” method, would be much better, but I don’t see ambiguity on deep vs shallow cloning.

    – supercat

    Jan 12, 2011 at 18:35


  • 37

    Your example illustrates the problem. Suppose you have a Dictionary<string, Customer>. Should the cloned Dictionary have the same Customer objects as the original, or copies of those Customer objects? There are reasonable use cases for either one. But ICloneable doesn’t make clear which one you’ll get. That’s why it’s not useful.

    Jan 12, 2011 at 18:53

  • @Kyralessa The Microsoft MSDN article actually states this very problem of not knowing if you are requesting a deep or shallow copy.

    – crush

    May 28, 2014 at 19:05

  • The answer from the duplicate stackoverflow.com/questions/129389/… describes Copy extension, based on recursive MembershipClone

    Jan 23, 2018 at 12:15