- class Program
- {
-
-
- <summary>
-
-
-
-
-
-
-
-
-
- public delegate TResult Func<T1, TResult>(T1 arg1);
-
-
- <summary>
-
-
-
-
- static Dictionary<Type, Delegate> _cachedIL = new Dictionary<Type, Delegate>();
-
-
-
- <summary>
-
-
-
-
-
- static void Main(string[] args)
- {
- DoCloningTest(1000);
- DoCloningTest(10000);
- DoCloningTest(100000);
-
-
-
- Console.ReadKey();
- }
-
-
-
- <summary>
-
-
-
-
-
- private static void DoCloningTest(int count)
- {
-
- HiPerfTimer timer = new HiPerfTimer();
- double timeElapsedN = 0, timeElapsedR = 0, timeElapsedIL = 0;
-
- Console.WriteLine("--> Creating {0} objects...", count);
- timer.StartNew();
- List<Person> personsToClone = CreatePersonsList(count);
- timer.Stop();
- Person temp = CloneObjectWithIL(personsToClone[0]);
- temp = null;
- Console.WriteLine("\tCreated objects in {0} seconds", timer.Duration);
-
- Console.WriteLine("- Cloning Normal...");
- List<Person> clonedPersons = new List<Person>(count);
- timer.StartNew();
- foreach (Person p in personsToClone)
- {
- clonedPersons.Add(CloneNormal(p));
- }
- timer.Stop();
- timeElapsedN = timer.Duration;
-
- Console.WriteLine("- Cloning IL...");
- clonedPersons = new List<Person>(count);
- timer.StartNew();
- foreach (Person p in personsToClone)
- {
- clonedPersons.Add(CloneObjectWithIL<Person>(p));
- }
- timer.Stop();
- timeElapsedIL = timer.Duration;
-
- Console.WriteLine("- Cloning Reflection...");
- clonedPersons = new List<Person>(count);
- timer.StartNew();
- foreach (Person p in personsToClone)
- {
- clonedPersons.Add(CloneObjectWithReflection(p));
- }
- timer.Stop();
- timeElapsedR = timer.Duration;
-
- Console.WriteLine();
- Console.ForegroundColor = ConsoleColor.Green;
- Console.WriteLine("----------------------------------------");
- Console.WriteLine("Object count:\t\t{0}", count);
- Console.WriteLine("Cloning Normal:\t\t{0:00.0000} s", timeElapsedN);
- Console.WriteLine("Cloning IL:\t\t{0:00.0000} s", timeElapsedIL);
- Console.WriteLine("Cloning Reflection:\t{0:00.0000} s", timeElapsedR);
- Console.WriteLine("----------------------------------------");
- Console.ResetColor();
- }
-
-
-
- <summary>
-
-
-
-
-
-
- private static List<Person> CreatePersonsList(int count)
- {
- Random r = new Random(Environment.TickCount);
- List<Person> persons = new List<Person>(count);
- for (int i = 0; i < count; i++)
- {
- Person p = new Person();
- p.ID = r.Next();
- p.Name = string.Concat("Slaets_", r.Next());
- p.FirstName = string.Concat("Filip_", r.Next());
- persons.Add(p);
- }
- return persons;
- }
-
-
-
- <summary>
-
-
-
-
-
-
- private static Person CloneObjectWithReflection(Person p)
- {
-
- FieldInfo[] fis = p.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
-
- Person newPerson = new Person();
-
-
- foreach (FieldInfo fi in fis)
- {
- fi.SetValue(newPerson, fi.GetValue(p));
- }
-
- return newPerson;
- }
-
-
-
- <summary>
-
-
-
-
-
-
-
-
-
- private static T CloneObjectWithIL<T>(T myObject)
- {
- Delegate myExec = null;
- if (!_cachedIL.TryGetValue(typeof(T), out myExec))
- {
-
- DynamicMethod dymMethod = new DynamicMethod("DoClone", typeof(T), new Type[] { typeof(T) }, true);
- ConstructorInfo cInfo = myObject.GetType().GetConstructor(new Type[] { });
-
- ILGenerator generator = dymMethod.GetILGenerator();
-
- LocalBuilder lbf = generator.DeclareLocal(typeof(T));
-
-
- generator.Emit(OpCodes.Newobj, cInfo);
- generator.Emit(OpCodes.Stloc_0);
- foreach (FieldInfo field in myObject.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic))
- {
-
- generator.Emit(OpCodes.Ldloc_0);
-
- generator.Emit(OpCodes.Ldarg_0);
-
- generator.Emit(OpCodes.Ldfld, field);
-
-
- generator.Emit(OpCodes.Stfld, field);
- }
-
-
- generator.Emit(OpCodes.Ldloc_0);
-
- generator.Emit(OpCodes.Ret);
-
- myExec = dymMethod.CreateDelegate(typeof(Func<T, T>));
- _cachedIL.Add(typeof(T), myExec);
- }
- return ((Func<T, T>)myExec)(myObject);
- }
-
-
-
- <summary>
-
-
-
-
-
-
- private static Person CloneNormal(Person p)
- {
- Person newPerson = new Person();
- newPerson.ID = p.ID;
- newPerson.Name = p.Name;
- newPerson.FirstName = p.FirstName;
- return newPerson;
- }
- }
-
Different ways of Object Cloning
Object Cloning is broadly categorized into Shallow copy and Deep copy. This article is not about shallow Copy and deep copy so will just give a brief introduction.
Shallow Copy
Copy the reference but not referenced object.
Deep Copy
Copy the reference and referenced objects.
Multiple ways to create clone of Object,
Clone Manually (ICloneable Interface)
This is simple but not ra ecommended way to create object as it does not specify if the object cloning is done by Deep copy approach or Shallow copy approach.
- using System;
-
- class Rock : ICloneable
- {
- int _weight;
- bool _round;
- bool _mossy;
-
- public Rock(int weight, bool round, bool mossy)
- {
- this._weight = weight;
- this._round = round;
- this._mossy = mossy;
- }
- public object Clone()
- {
- return new Rock(this._weight, this._round, this._mossy);
- }
-
- public override string ToString()
- {
- return string.Format("weight = {0}, round = {1}, mossy = {2}",
- this._weight,
- this._round,
- this._mossy);
- }
- }
- class Program
- {
- static void Main()
- {
- Rock rock1 = new Rock(10, true, false);
- Rock rock2 = rock1.Clone() as Rock;
-
- Console.WriteLine("1. {0}", rock1.ToString());
- Console.WriteLine("2. {0}", rock2.ToString());
- Console.ReadLine();
- }
- }
Clone using MemberwiseClone
- using System;
-
- class Rock
- {
- int _weight;
- bool _round;
- bool _mossy;
-
- public Rock(int weight, bool round, bool mossy)
- {
- this._weight = weight;
- this._round = round;
- this._mossy = mossy;
- }
-
-
- public Rock ShallowCopy()
- {
- return (Rock)this.MemberwiseClone();
- }
-
-
-
-
- public override string ToString()
- {
- return string.Format("weight = {0}, round = {1}, mossy = {2}",
- this._weight,
- this._round,
- this._mossy);
- }
- }
-
- class Program
- {
- static void Main()
- {
- Rock rock1 = new Rock(10, true, false);
- Rock rock2 = rock1.ShallowCopy();
-
- Console.WriteLine("1. {0}", rock1.ToString());
- Console.WriteLine("2. {0}", rock2.ToString());
- Console.ReadLine();
- }
- }
Note
This is shallow copy using MemberwiseClone. This can be modified a bit to implement deep copy as well.
Clone with Reflection
- using System;
- using System.IO;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- public static class ObjectClone
- {
- public static T Clone<T>(T RealObject)
- {
- using (Stream objectStream = new MemoryStream())
- {
- IFormatter formatter = new BinaryFormatter();
- formatter.Serialize(objectStream, RealObject);
- objectStream.Seek(0, SeekOrigin.Begin);
- return (T)formatter.Deserialize(objectStream);
- }
- }
- }
Clone with IL
- class Program
- {
-
-
- <summary>
-
-
-
-
-
-
-
-
-
- public delegate TResult Func<T1, TResult>(T1 arg1);
-
-
- <summary>
-
-
-
-
- static Dictionary<Type, Delegate> _cachedIL = new Dictionary<Type, Delegate>();
-
-
-
- <summary>
-
-
-
-
-
- static void Main(string[] args)
- {
- DoCloningTest(1000);
- DoCloningTest(10000);
- DoCloningTest(100000);
-
-
-
- Console.ReadKey();
- }
-
-
-
- <summary>
-
-
-
-
-
- private static void DoCloningTest(int count)
- {
-
- HiPerfTimer timer = new HiPerfTimer();
- double timeElapsedN = 0, timeElapsedR = 0, timeElapsedIL = 0;
-
- Console.WriteLine("--> Creating {0} objects...", count);
- timer.StartNew();
- List<Person> personsToClone = CreatePersonsList(count);
- timer.Stop();
- Person temp = CloneObjectWithIL(personsToClone[0]);
- temp = null;
- Console.WriteLine("\tCreated objects in {0} seconds", timer.Duration);
-
- Console.WriteLine("- Cloning Normal...");
- List<Person> clonedPersons = new List<Person>(count);
- timer.StartNew();
- foreach (Person p in personsToClone)
- {
- clonedPersons.Add(CloneNormal(p));
- }
- timer.Stop();
- timeElapsedN = timer.Duration;
-
- Console.WriteLine("- Cloning IL...");
- clonedPersons = new List<Person>(count);
- timer.StartNew();
- foreach (Person p in personsToClone)
- {
- clonedPersons.Add(CloneObjectWithIL<Person>(p));
- }
- timer.Stop();
- timeElapsedIL = timer.Duration;
-
- Console.WriteLine("- Cloning Reflection...");
- clonedPersons = new List<Person>(count);
- timer.StartNew();
- foreach (Person p in personsToClone)
- {
- clonedPersons.Add(CloneObjectWithReflection(p));
- }
- timer.Stop();
- timeElapsedR = timer.Duration;
-
- Console.WriteLine();
- Console.ForegroundColor = ConsoleColor.Green;
- Console.WriteLine("----------------------------------------");
- Console.WriteLine("Object count:\t\t{0}", count);
- Console.WriteLine("Cloning Normal:\t\t{0:00.0000} s", timeElapsedN);
- Console.WriteLine("Cloning IL:\t\t{0:00.0000} s", timeElapsedIL);
- Console.WriteLine("Cloning Reflection:\t{0:00.0000} s", timeElapsedR);
- Console.WriteLine("----------------------------------------");
- Console.ResetColor();
- }
-
-
-
- <summary>
-
-
-
-
-
-
- private static List<Person> CreatePersonsList(int count)
- {
- Random r = new Random(Environment.TickCount);
- List<Person> persons = new List<Person>(count);
- for (int i = 0; i < count; i++)
- {
- Person p = new Person();
- p.ID = r.Next();
- p.Name = string.Concat("Slaets_", r.Next());
- p.FirstName = string.Concat("Filip_", r.Next());
- persons.Add(p);
- }
- return persons;
- }
-
-
-
- <summary>
-
-
-
-
-
-
- private static Person CloneObjectWithReflection(Person p)
- {
-
- FieldInfo[] fis = p.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
-
- Person newPerson = new Person();
-
-
- foreach (FieldInfo fi in fis)
- {
- fi.SetValue(newPerson, fi.GetValue(p));
- }
-
- return newPerson;
- }
-
-
-
- <summary>
-
-
-
-
-
-
-
-
-
- private static T CloneObjectWithIL<T>(T myObject)
- {
- Delegate myExec = null;
- if (!_cachedIL.TryGetValue(typeof(T), out myExec))
- {
-
- DynamicMethod dymMethod = new DynamicMethod("DoClone", typeof(T), new Type[] { typeof(T) }, true);
- ConstructorInfo cInfo = myObject.GetType().GetConstructor(new Type[] { });
-
- ILGenerator generator = dymMethod.GetILGenerator();
-
- LocalBuilder lbf = generator.DeclareLocal(typeof(T));
-
-
- generator.Emit(OpCodes.Newobj, cInfo);
- generator.Emit(OpCodes.Stloc_0);
- foreach (FieldInfo field in myObject.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic))
- {
-
- generator.Emit(OpCodes.Ldloc_0);
-
- generator.Emit(OpCodes.Ldarg_0);
-
- generator.Emit(OpCodes.Ldfld, field);
-
-
- generator.Emit(OpCodes.Stfld, field);
- }
-
-
- generator.Emit(OpCodes.Ldloc_0);
-
- generator.Emit(OpCodes.Ret);
-
- myExec = dymMethod.CreateDelegate(typeof(Func<T, T>));
- _cachedIL.Add(typeof(T), myExec);
- }
- return ((Func<T, T>)myExec)(myObject);
- }
-
-
-
- <summary>
-
-
-
-
-
-
- private static Person CloneNormal(Person p)
- {
- Person newPerson = new Person();
- newPerson.ID = p.ID;
- newPerson.Name = p.Name;
- newPerson.FirstName = p.FirstName;
- return newPerson;
- }
- }
Clone with Extension Methods
I found this blog and it’s great. I am providing the link here.
P.S.
There is nothing much new in this article here asI already found similar writing online. I hope this article enlarges the scope of its original article .This article I will keep for my personal knowledge repository