Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a Deep Copy in C#

Tags:

c#

deep-copy

I want to make a deep copy of an object so I could change the the new copy and still have the option to cancel my changes and get back the original object.

My problem here is that the object can be of any type, even from an unknown assembly. I can not use BinaryFormatter or XmlSerializer, because the object unnecessarily have [Serializable] attribute.

I have tried to do this using the Object.MemberwiseClone() method:

public object DeepCopy(object obj)
{
    var memberwiseClone = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

    var newCopy = memberwiseClone.Invoke(obj, new object[0]);

    foreach (var field in newCopy.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
    {
        if (!field.FieldType.IsPrimitive && field.FieldType != typeof(string))
        {
            var fieldCopy = DeepCopy(field.GetValue(newCopy));
            field.SetValue(newCopy, fieldCopy);
        }
    }
    return newCopy;
}

The problem in this is that it's not working on an enumerable (array, list etc.), an not on dictionary.

So, how can I make a deep copy of an unknown object in C#?

TNX a lot!

like image 309
Orad SA Avatar asked Sep 05 '10 17:09

Orad SA


3 Answers

It is completely impossible to deep-copy an arbitrary object.

For example, how would you handle a Control or a FileStream or an HttpWebResponse?

Your code cannot know how the object works and what its fields are supposed to contain.

Do not do this.
It's a recipe for disaster.

like image 172
SLaks Avatar answered Dec 04 '22 18:12

SLaks


Making a deep copy of an arbitrary object is quite difficult. What if the object contains access to a resource such as an open file with write capabilities, or a network connection? Without knowing what type of information the object holds, I would be hard to make a copy of an object, and have it function exactly the same way. You might be able to use reflection to do this, but it would get quite difficult. For starters you'd have to have some kind of list to keep all the objects you copied, otherwise, if A references B and B references A, then you might end up in an endless loop.

like image 35
Kibbee Avatar answered Dec 04 '22 18:12

Kibbee


Agree with SLaks. You allways need custom copying semantics just to distingush between weather you want to have a deep copy or a flat copy. (What is a reference, what a contained reference in a sens of composite reference.)

The pattern you are talking about is the memento pattern.

Read the article on how to implement it. But basically it turns out to create a custom copy facitlity. Either internal in the class or external in a "copy factory".

like image 39
schoetbi Avatar answered Dec 04 '22 20:12

schoetbi