Cloning C# objects is one of those things that appears easy but is actually quite complicated with many “gotchas.” This article describes the most common ways to clone a C# object.
Shallow vs. Deep Cloning
There are two types of object cloning: shallow and deep. A shallow clone copies the references but not the referenced objects. A deep clone copies the referenced objects as well.
Hence, a reference in the original object and the same reference in a shallow-cloned object both point to the same object. Whereas a deep-cloned object contains a copy of everything directly or indirectly referenced by the object. See wikipedia for a detailed explanation.
ICloneable Interface
The ICloneable interface contains a single Clone method, which is used to create a copy of the current object.
public interface ICloneable { object Clone(); }
The problem with ICloneable is that the Clone method does not explicitly specify whether it is performing a shallow or deep copy, so callers can never be sure. Hence, there is some discussion about making ICloneable obsolete in the .NET Framework. The MSDN documentation seems to hint that Clone should perform a deep copy, but it is never explicitly stated:
The ICloneable interface contains one member, Clone, which is intended to support cloning beyond that supplied by MemberWiseClone… The MemberwiseClone method creates a shallow copy…
Type-Safe Clone
Another disadvantage of ICloneable is that the Clone method returns an object, hence every Clone call requires a cast:
Person joe = new Person(); joe.Name = "Joe Smith"; Person joeClone = (Person)joe.Clone();
One way to avoid the cast is to provide your own type-safe Clone method. Note that you must still provide the ICloneable.Clone method to satisfy the ICloneable interface:
public class Person : ICloneable { public string Name; object ICloneable.Clone() { return this.Clone(); } public Person Clone() { return (Person)this.MemberwiseClone(); } }
Clone Options
Following are some of the more common approaches to clone a C# object:
1. Clone Manually
One way to guarantee that an object will be cloned exactly how you want it is to manually clone every field in the object. The disadvantage to this method is it’s tedious and error prone: if you add or change a field in the class, chances are you will forget to update the Clone method. Note that care must be taken to avoid an infinite loop when cloning referenced objects that may refer back to the original object. Here is a simple example that performs a deep copy:
public class Person : ICloneable { public string Name; public Person Spouse; public object Clone() { Person p = new Person(); p.Name = this.Name; if (this.Spouse != null) p.Spouse = (Person)this.Spouse.Clone(); return p; } }
2. Clone with MemberwiseClone
MemberwiseClone is a protected method in the Object class that creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object. For value-type fields, this performs a bit-by-bit copy. For reference-type fields, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object. Note this works for all derived classes, and hence you only need to define the Clone method once in the base class. Here is a simple example:
public class Person : ICloneable { public string Name; public Person Spouse; public object Clone() { return this.MemberwiseClone(); } }
3. Clone with Reflection
Cloning by Reflection uses Activator.CreateInstance to create a new object of the same type, then performs a shallow copy of each field using Reflection. The advantage of this method is it’s automated and does not need to be adjusted when members are added or removed from the object. Also, it can be written to provide a deep copy. The disadvantage is it uses Reflection, which is slower and not allowed in partial trust environments. Sample code
4. Clone with Serialization
One of the easiest ways to clone an object is to serialize it and immediately deserialize it into a new object. Like the Reflection approach, the Serialization approach is automated and does not need to be adjusted when members are added or removed from the object. The disadvantage is that serialization can be slower than other methods including Reflection, and all cloned and referenced objects must be marked Serializable. Also, depending on what type of serialization you use (XML, Soap, Binary), private members may not be cloned as desired. Sample code here and here and here.
5. Clone with IL
A fringe solution is to use IL (Intermediate Language) to clone objects. This approach creates a DynamicMethod, gets the ILGenerator, emits code in the method, compiles it to a delegate, and executes the delegate. The delegate is cached so that the IL is generated only the first time and not for each subsequent cloning. Although this approach is faster than Reflection, it is difficult to understand and maintain. Sample code
6. Clone with Extension Methods
Havard Stranden created a custom cloning framework using extension methods. The framework creates a deep copy of an object and all referenced objects, no matter how complex the object graph is. The disadvantage is this is a custom framework with no source code (Update: source code now included, see comment below), and it cannot copy objects created from private classes without parameterless constructors. Another problem, which is common to all automated deep copy methods, is that deep copying often requires intelligence to handle special cases (such as unmanaged resources) that cannot be easily automated.
Cloning is indeed a fundamental aspect of C# (particulary in relation with the concept of immutability). I did not expect to learn something new about it… until I read your 2 last paragraphs (IL and extension methods)! Thanks a lot for this very interesting post.
Hi, great article. I have made the source code for the Copyable framework available from the article. This hopefully makes the framework more understandable and easier to use, as well as easy to extend. Please send me any contributions.
Thanks!
Hi, great article. In a few lines, everything about cloning was explained. Thanks.
[…] C# Object Clone Wars […]
Thanks a lot! 🙂
Many thanks, dude. Really helpfull
[…] Read more: https://www.csharp411.com/c-object-clone-wars/ […]
Perfect! I had no idea the other methods existed. I was really dreading manually mapping 30+ fields and then maintaining them. What a time-saver. Thanks!
Excellent Article…!!
Many Thanks for this…
You just saved me hours of research. Great Article.
Many thanks! Clear, excellent.
Thanks for your clear article.. And also it is not boring, tahnks again.
Thanks, man.
Great article!!
Fantastic article! You saved me a ton of research time today.
Old C-dog learns new tricks … very good review, much appreciated!
Thanks a lot for the 2 last paragraphs, i didn’t know about it.
FYI all the Copyable Extensions (option 6) are doing is using reflection so the performance is still not going to be great….
A very thoughtful/nice comparison of different approaches to clone.
Thank you for method “Clone with IL” 🙂
Thank you, great article.
I always choose to clone manually.
Probably the best performance and it isn’t tedious and error prone when you use T4 to generate the methods.
[…] N.B -> C# Object Clone Wars […]
[…] you want to use some other deep copy approach instead this article lists several others so I would suggest not trying to write your […]
IMPLEMENTATION and COMPARISON of Serialization, Reflection and Extension methods with all codes and tests can be found on:
http://www.codeproject.com/Articles/1111658/Fast-Deep-Copy-of-Objects-by-Expression-Trees-Csha