using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
public static void Main()
Console.WriteLine("\n=========================\n");
Console.WriteLine("Compare Performance\n");
Console.WriteLine("Approach".PadRight(30) + "First Call".PadRight(20) + "Second Call".PadRight(20) + "100 Calls".PadRight(20));
CheckPerformance(Program.CloneWithSystemTextJsonSerializer, "System.Text.Json Serializer");
CheckPerformance(Program.CloneWithJsonNetSerializer, "Json.NET Serializer");
CheckPerformance(Program.CloneWithBinarySerializer, "Binary Serializer");
CheckPerformance(Program.CloneWithICloneable, "ICloneable");
CheckPerformance(Program.CloneWithReflection, "Reflection");
CreateCloneAndTest(Program.CloneWithSystemTextJsonSerializer, "System.Text.Json Serializer");
CreateCloneAndTest(Program.CloneWithJsonNetSerializer, "Json.NET Serializer");
CreateCloneAndTest(Program.CloneWithBinarySerializer, "Binary Serializer");
CreateCloneAndTest(Program.CloneWithICloneable, "ICloneable");
CreateCloneAndTest(Program.CloneWithReflection, "Reflection");
public static Customer CloneWithSystemTextJsonSerializer(Customer customer)
var clone = CloneGenericWithSystemTextJsonSerializer(customer);
public static T CloneGenericWithSystemTextJsonSerializer<T>(T source)
var cloneJson = JsonSerializer.Serialize(source);
var clone = JsonSerializer.Deserialize<T>(cloneJson);
public static Customer CloneWithJsonNetSerializer(Customer customer)
var clone = CloneGenericWithJsonNetSerializer(customer);
public static T CloneGenericWithJsonNetSerializer<T>(T source)
if (!typeof(T).IsSerializable)
throw new ArgumentException("The type must be serializable.", nameof(source));
var cloneJson = Newtonsoft.Json.JsonConvert.SerializeObject(source);
var clone = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(cloneJson);
public static Customer CloneWithBinarySerializer(Customer customer)
var clone = CloneGenericWithBinarySerializer(customer);
public static T CloneGenericWithBinarySerializer<T>(T source)
if (!typeof(T).IsSerializable)
throw new ArgumentException("The type must be serializable.", nameof(source));
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
public static Customer CloneWithICloneable(Customer customer)
var clone = (Customer)customer.Clone();
public static Customer CloneWithReflection(Customer customer)
var clone = (Customer)CloneObjectWithReflection(customer);
public static object CloneObjectWithReflection(object obj)
Type type = obj.GetType();
object clone = Activator.CreateInstance(type);
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var property in properties)
if (property.PropertyType.IsValueType || property.PropertyType.IsEnum || property.PropertyType.Equals(typeof(System.String)))
property.SetValue(clone, property.GetValue(obj, null), null);
var objPropertyValue = property.GetValue(obj, null);
if (objPropertyValue == null)
property.SetValue(clone, null, null);
property.SetValue(clone, CloneObjectWithReflection(objPropertyValue), null);
public static void CreateCloneAndTest(Func<Customer, Customer> cloneFunction, string approachName)
Console.WriteLine("\n=========================\n");
Console.WriteLine("Approach: " + approachName + Environment.NewLine);
var customer = CreateCustomer();
var clone = cloneFunction(customer);
if ((customer.LastName == clone.LastName) &&
(customer.Address.City == clone.Address.City) &&
(customer.Address.State.TwoLetterCode == clone.Address.State.TwoLetterCode))
Console.WriteLine("Result: Success");
Console.WriteLine("Result: Failed");
Console.WriteLine("Clone: " + Environment.NewLine + JsonSerializer.Serialize(clone, new JsonSerializerOptions { WriteIndented = true }));
public static void CheckPerformance(Func<Customer, Customer> cloneFunction, string approachName)
var customer = CreateCustomer();
var stopwatch = new Stopwatch();
var clone = cloneFunction(customer);
var firstDuration = stopwatch.Elapsed;
clone = cloneFunction(customer);
var secondDuration = stopwatch.Elapsed;
for (int i = 0; i <= 100; i++)
clone = cloneFunction(customer);
var oneHundredDuration = stopwatch.Elapsed;
Console.WriteLine(approachName.PadRight(30) + (firstDuration.TotalMilliseconds + "ms").PadRight(20) + (secondDuration.TotalMilliseconds + "ms").PadRight(20) + (oneHundredDuration.TotalMilliseconds + "ms").PadRight(20));
public static Customer CreateCustomer()
State = new State {Name = "Oregon", TwoLetterCode = "OR"}
public class Customer : ICloneable
public string Id {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public Address Address {get; set;}
var newCustomer = (Customer)this.MemberwiseClone();
newCustomer.Address = (Address)this.Address.Clone();
public class Address : ICloneable
public string Street {get; set;}
public string City {get; set;}
public State State {get; set;}
var newAddress = (Address)this.MemberwiseClone();
newAddress.State = (State)this.State.Clone();
public class State : ICloneable
public string Name {get; set;}
public string TwoLetterCode {get; set;}
var newState = (State)this.MemberwiseClone();