I want to create deep copy method and I found 3 ways to execute it
1-deep copy with pass each property 1 by 1
2-using reflection
3-using serializatio
As the author of CGbR I would like to invite you to give it a try for your use case.
All you need is the nuget package and a partial class definition that implements ICloneable
. The generated will then create a file next to it with a Clone(bool deep)
method.
public partial class Root : ICloneable
{
public Root(int number)
{
_number = number;
}
private int _number;
public Partial[] Partials { get; set; }
public IList<ulong> Numbers { get; set; }
public object Clone()
{
return Clone(true);
}
private Root()
{
}
}
public partial class Root
{
public Root Clone(bool deep)
{
var copy = new Root();
// All value types can be simply copied
copy._number = _number;
if (deep)
{
// In a deep clone the references are cloned
var tempPartials = new Partial[Partials.Length];
for (var i = 0; i < Partials.Length; i++)
{
var value = Partials[i];
value = value.Clone(true);
tempPartials[i] = value;
}
copy.Partials = tempPartials;
var tempNumbers = new List<ulong>(Numbers.Count);
for (var i = 0; i < Numbers.Count; i++)
{
var value = Numbers[i];
tempNumbers[i] = value;
}
copy.Numbers = tempNumbers;
}
else
{
// In a shallow clone only references are copied
copy.Partials = Partials;
copy.Numbers = Numbers;
}
return copy;
}
}
Performance: In a benchmark for a clone we needed at work the compared it to DataContractSerializer
and MemoryStream
. The generated code is 600x faster.
Order you listed your possible solutions is correct performance order.
You will get best performance when you write the code to clone each property value manually.
Reflection will have similar result as manually cloning but little slower.
Serialization is the worst scenario. But quickest to implement.
Here is a good article that describes other possible solutions.
So here is a list of all possible cloning methods:
Me personally would go with "Clone with IL" as it is slightly faster than reflection and you don't have to clone everything manually.
The first option, manually deep copying your values, will be the most performant by far.
Reflection will introduce quite a bit of overhead, as it is (relatively) slow to access data.
Serialization is adding a huge cost, as it serializes the data into a temporary structure, then reverses the process to set. This is again, very slow.
The only advantage to option 2 or 3 is that its potentially easier to implement, and reusable across multiple types. The first option has to be hand-written per type, but is much faster (and more efficient in memory usage than option 3, as well).
Reflection can be use to produce DynamicMethod which can be more efficient than manually copy (auto-properties can be copied by accessing fields directly breaking scope via skipVisibilityCheck). DynamicMethod offer you a delegate you can keep in static readonly field to clone your object. This is the fast and easy way to do it but not forcely the cleanest. Serialization is slow and not adapted.
There's the ICloneable interface. If cloning something ICloneable, using its methods would be best solution
Sounds like you've done the hard work of finding the ways to do it, so now you'll have to test them all in your specific situation and find out.
For the most part, it really depends on what data you're serializing