From what I've read from the C# 6.0 Cookbook, the best way to do this is to create your own ShallowClone and DeepClone interfaces, then implement them. The reason it's not suggested to use ICloneable is due to the confusion around whether or not ICloneable creates a DeepClone or a ShallowClone, so instead make your own interfaces if Microsoft's don't work.
ShallowClone is recreating the object with all it's properties having the same reference (two different objects referencing the same properties)
DeepClone is recreating the object with new properties.
To do the ShallowClone, the following works:
public ShallowClone ShallowCopy() => (ShallowClone)this.MemberwiseClone();
And for the DeepClone:
public DeepClone DeepCopy()
{
BinaryFormatter BF = new BinaryFormatter();
MemoryStream memStream = new MemoryStream();
BF.Serialize(memStream, this);
memStream.Flush();
memStream.Position = 0;
return (DeepClone)BF.Deserialize(memStream);
}
Stolen straight from the book, so all credit goes there. I just remember that this is the way it "should" be done in C#. There may still be a better way however, especially seen as we're at C# 8.0 now.
You can just write your own ShallowClone and DeepClone methods, and assign each property or create new properties, but this is tedious, hence why the above methods are so useful.
So the idea is you implement these interfaces on the objects you want to clone, and then use the methods.
I was thinking of making these extension methods instead, but it doesn't work. My idea was something like:
public static class CloningExtention
{
public static T ShallowClone(this T obj) => (T)obj.MemberwiseClone(); // Doesn't work
public static T DeepClone(this T obj)
{
BinaryFormatter BF = new BinaryFormatter();
MemoryStream memStream = new MemoryStream();
BF.Serialize(memStream, this);
memStream.Flush();
memStream.Position = 0;
return (T)BF.Deserialize(memStream);
};
}
But MemberwiseClone is a protected method, so extension methods don't work. Why is it protected? I have no idea, but if I had to guess, it'd be because there is a very good reason why you shouldn't be cloning objects anywhere you like.
However, I still wanted to demonstrate it, so you know not to do it. If anyone knows why this method is protected, please let me know.