Click here to Skip to main content
15,888,286 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
In .NET I want to make a deep copy of an Object. But how deep is exactly deep?
For example, I have a SalesOrder Class. I could deep copy it by creating a new SalesOrder Object and copy all value types into the new Object. However, a SalesOrder has a collection of SalesOrderDetails. Luck has it that the SalesOrderDetail Class does not have a DeepClone Method, so I will have to copy every SalesOrderDetail Object in the SalesOrder... Here comes the fun part, every SalesOrderDetail has a Product, which also does not have a DeepClone Method (are there ANY .NET Classes that have this Method?).
In the case of, for example, Entity Framework every Product has a list of SalesOrderDetails which again have a SalesOrder and the circle is complete... Entity Framework uses lazy loading to not load an entire database into your application at once. But when you're going to clone you effectively need to call every Object in case it exists and needs to be cloned.

I've Googled around and I've seen many people saying Serialization is the easiest way to create a deep copy of an Object, but my experience is that many (non-custom made) Classes cannot be Serialized just like that (circular references etc.) if they can be serialized at all.

So how deep should a deep copy actually go and is it even possible to create a perfect deep copy of a more complex Object? I guess Reflection might take you pretty far, but this too is far from ideal (although preferred above Serialization for me).

Any thoughts?
Thanks.
Posted

It totally depends on your needs. You won't copy anything just for the sake of copying it. Instead you definitely have a requirement that uses desired copy. This requirement dictates what should be included in your copy.

Serialization is not that bad. It can handle circular references pretty well, if you refrain from using XMLSerializer. Stick to BinaryFormatter or SOAPFormatter instead. But be warned. Using them in a least-possible-amount-of-coding approach will copy everything related to your object. You have to carefully exclude things, which again leads to the requirement mentioned above.
 
Share this answer
 
Comments
Sander Rossel 16-Dec-11 4:41am    
Thanks for your answer. However, like many others have said, you again mention Serialization.
But that does require me to make any Object I might want to clone Serializable. I don't always have that option :)
Let's just say, for 'simplicity', that I want a generic Method that can deep copy ANY Object I might pass to it.
lukeer 16-Dec-11 8:53am    
I mentioned serialization because you did. Now, I'd wrap a class that I don't have access to in another class. Declare it [Serializable] and call every method/property you need to create a serialized version of the wrapper on the wrapped class.

And again, the serialization depth will depend on your requirements.

With reflection you will have to deal with an overwhelminly huge amount of accessible data, handle circular references yourself and take care of your requirements.
Sander Rossel 16-Dec-11 13:19pm    
I don't think Serialization works that way... If I need to Serialize an Object that is not Serializable it won't be Serializable by just wrapping it in another Object that IS Serializable... You are right about Reflection, but I do think Reflection has more possibilities because it can sort of break into the system (get fields that would normally be Private etc.). On top of that it is not limited to Classes that have the Serializable Attribute (although Mehdi appearently somehow got around this limitation).
I am just curious to solutions that do not involve Serialization. Although Serialization does seem like the easiest option.
By the way, I don't really have requirements, I was just curious how such problems could be solved :)
lukeer 19-Dec-11 2:27am    
In terms of Reflection, we seem to agree that the possibilities are as huge as the complexity that comes with its use.

Of course I did not mean that you can make an object serializable just by wrapping it. But you can wrap it in another object. You can declare the wrapper [Serializable]. And you can do whatever you want in the GetObjectData(SerializationInfo info, StreamingContext context) and in the Constructor(SerializationInfo info, StreamingContext context) methods.
Sander Rossel 19-Dec-11 3:15am    
Ah, now that makes sense. I haven't really done enough with Serialization to have needed the GetObjectData and the SerializationInfo, StreamingContext constructor, so those are actually very good tips. Thanks for your answer! :)
Depending on your serializer it will go as deep as the serializer goes.

For example if you are using the Binaryformater it will create a copy of all the objects referenced, including circular references.

For other serializers usually circular references are ignored or broken out of at a certain depth (in my fastJSON serializer I have set this to 10 deep)
 
Share this answer
 
Comments
Sander Rossel 16-Dec-11 4:40am    
Thanks for your answer. However, like many others have said, you again mention Serialization.
But that does require me to make any Object I might want to clone Serializable. I don't always have that option :)
Let's just say, for 'simplicity', that I want a generic Method that can deep copy ANY Object I might pass to it.
Mehdi Gholam 16-Dec-11 10:46am    
Most cloning is done by serializers, and yes if you are using BinaryFormatter you must supply a serializable attribute.

However my fastJSON does not require the attribute and will work with any POCO.
Sander Rossel 16-Dec-11 13:25pm    
I must admit I've never worked with JSON. But Serializing Objects that are not marked as Serializable sounds interesting. I guess I should check out both JSON and your fastJSON article. I'm guessing I won't learn to use JSON over night though, so I guess my cloning adventure is parked for a while :)
Mehdi Gholam 16-Dec-11 13:36pm    
Don't give up it's dead simple actually.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900