Clone Object in C#

A quick tip on how to clone any object in your app. Sometimes you need a copy of an object, but don’t want to affect the original. You can either copy across all values to a new object manually, or even use AutoMapper. However, here I have a quick easy way to clone an object, and making a second instance.

Performance

A note about performance before we begin. This approach is only recommended, if you have a small number of complex objects, that needs cloning. Running a few tests, using JSON Serialization/Deserialization takes about 330ms for 100 objects with 10 properties, or only 460ms with 10,000 objects. The performance hit here seems to be in the reflection, rather than the actual number of objects. That’s the price you pay for easier code. As this code doesn’t break, when you change the model.

If you use the ICloneable interface, and manually implement property copying, this is down to 1-2ms. If performance if certainly an issue, then I would suggest implementing manual cloning. However, you will always need to remember to update the Clone method, every time you add a property. JSON Serialization is good if you have complex objects with many properties, and performance at this point is not going to be a major concern.

Special Note: JSON Serialization and Deserialization of 100 objects performance can be improved to ~140ms, if you use fastJson and DeepCopy.

// Use this in the Clone extension method below, instead of Newtonsoft.Json
fastJSON.JSON.DeepCopy(instance);

Prerequisites

  • Download Newstonsoft.Json. I imagine you probably have this installed already, since being the most popular Nuget package.

Extension

Here, I create an extension, that allows you to use a Fluent API to clone any object.

public static class Extensions
{
    public static T Clone<T>(this T instance)
    {
        var json = JsonConvert.SerializeObject(instance);
        return JsonConvert.DeserializeObject<T>(json);
    }
}

You can then do this on any object.

var newInstance = myObject.Clone();

This clone works, by converting the object into a string, and then from a string back into a new instance of the object, and it is very effective.

JsonConverters

Not all objects convert so easily. Often you will have an interface in the object. To serialize, this is fine, but on deserialization, it doesn’t know what instance to turn that interface into it. This is where JsonConverters come in, and you can tell Newtonsoft.Json, which instance to convert an interface into. I created a simple generic converter to help with this.

First create the converter as shown.

public class InterfaceConverter<I, T> : JsonConverter
{
    public override bool CanWrite => false;
    public override bool CanRead => true;
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(I);
    }
    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        throw new InvalidOperationException("Use the default serialization");
    }

    public override object ReadJson(JsonReader reader,
        Type objectType, object existingValue,
        JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);
        var deserialized = (T)Activator.CreateInstance(typeof(T));
        serializer.Populate(jsonObject.CreateReader(), deserialized);
        return deserialized;
    }
}

In your model, now add this attribute, with the Interface to Instance mapping.

[JsonConverter(typeof(InterfaceConverter<IInterface, InstanceType>))]
IInterface MyObject { get; }

Now when it deserializes, it will use this mapping to map the interface to an instance.


XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,400+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

10 Comments

  1. Alexandre Zollinger Chohfi

    If you don’t care about annotating your classes with [Serializable], I would go with the BinaryFormatter approach. It might depend, but it’s around 10 times faster.

    public static T Clone(this T instance)
    {
    using (var stream = new MemoryStream())
    {
    var formatter = new BinaryFormatter();
    formatter.Serialize(stream, instance);
    stream.Flush();
    stream.Position = 0;
    return (T)formatter.Deserialize(stream);
    }
    }

    1. Adam Pedley

      Thanks for the tip. Json serializing isn’t that performant and I would recommend something else, like your way, if you have a large number of items that need converting. But luckily for me so far, I haven’t had anything that big to clone.

  2. Alexandre Zollinger Chohfi

    I think I just typed total bullshit. I did a quick performance test and Json serializer was faster. That was on .Net Core, btw.

    1. Adam Pedley

      The more you know 🙂 Thanks for taking the time to perf test. I thought binary was faster as well, but I know that Newtonsoft.Json gets a lot of attention and work on perf.

  3. Hines V

    Great article!

    I believe you can also get around the interface issue by using the following JSON Serializer settings:

    new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.All
    }

    So your code would instead become:

    var json = JsonConvert.SerializeObject(instance, new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.All
    });

  4. Claudiu Tomescu

    The only benefit I can see for binary ser/deser is around private members; otherwise I’ll go with JSON ser/deser. As far as performance here is an interesting analysis of various ser/deser libs which I found a while ago and help me a lot: