tags:

views:

42879

answers:

13

I want to do something like...

myObject myObj = GetmyObj()//create and fill a new object
myObject newObj = myObj.Clone();

...and then make changes to the new object that are not reflected in the original object.

I don't often need this functionality so when it's been necessary I've resorted to creating a new object and then copying each property individually but it always leaves me with the feeling that there is a better/more elegant way of handling the situation.

How can I clone/deep copy an object so that the cloned object can be modified without any changes being reflected in the original object?

+1  A: 

Override clone.

Patrick
aka implement ICloneable, but it's about the same idea.
Nick
ICloneable doesn't have a generic interface, so it is not recommended to use that interface.
Karg
+12  A: 

Here's a good resource I've used in the past: C# Object Cloning

Ian P
+2  A: 

In general, you implement the ICloneable interface and implement Clone yourself. C# objects have a built-in MemberwiseClone method that performs a shallow copy that can help you out for all the primitives.

For a deep copy, there is no way it can know how to automatically do it.

HappyDude
ICloneable doesn't have a generic interface, so it is not recommended to use that interface.
Karg
Microsofts recommendation on the use of ICloneable: Don't. http://blogs.msdn.com/brada/archive/2004/05/03/125427.aspx
Bevan
+1  A: 

Here is a quick example that looks really interesting for duplicating memory...

http://www.c-sharpcorner.com/UploadFile/sd_surajit/cloning05032007012620AM/cloning.aspx

Sam
+1  A: 
  1. Basically you need to implement IClonable interface and then realize object structure copying.
  2. If it's deep copy of all members, you need to insure (not relating on solution you choose) that all children are clonable as well.
  3. Sometimes you need to be aware of some restriction during this process, for example if you copying the ORM objects most of frameworks allow only one object attached to the session and you MUST NOT make clones of this object, or if it's possible you need to care about session attaching of these objects.

Cheers.

dimarzionist
ICloneable doesn't have a generic interface, so it is not recommended to use that interface.
Karg
+5  A: 

I prefer a copy ctor to a clone. The intent is clearer.

Nick
.Net doesn't have copy constructors.
Pop Catalin
Sure it does: new MyObject(objToCloneFrom)Just declare a ctor which takes the object to clone as a parameter.
Nick
It's not the same thing. You have to add it to every class manually, and you don't even know if you're garantueeing a deep copy.
Dave Van den Eynde
+1 for copy ctor. You have to manually write a clone() function for each type of object too, and good luck with that when your class hierarchy gets a few levels deep.
Andrew Grant
+1. This is how XDocument does it.
RichardOD
+1  A: 

The short answer is you inherit from the ICloneable interface and then implement the .clone function. Clone should do a memberwise copy and perform a deep copy on any member that requires it, then return the resulting object. This is a recursive operation ( it requires that all members of the class you want to clone are either value types or implement ICloneable and that their members are either value types or implement ICloneable, and so on).

For a more detailed explanation on Cloning using ICloneable, check out this article:

http://www.ondotnet.com/pub/a/dotnet/2002/11/25/copying.html

The long answer is "it depends". As mentioned by others, ICloneable is not supported by generics, requires special considerations for circular class references, and is actually viewed by some as a "mistake" in the .NET Framework. The serialization method depends on your objects being serializable, which they may not be and you may have no control over. There is still much debate in the community over which is the "best" practice. In reality, none of the solutions are the one-size fits all best practice for all situations like ICloneable was originally interpreted to be.

See the this Developer's Corner article for a few more options (credit to Ian): http://developerscon.blogspot.com/2008/06/c-object-clone-wars.html

Burly
ICloneable doesn't have a generic interface, so it is not recommended to use that interface.
Karg
Your solution works until it needs to handle circular references, then things start to complicate, it's better to try implement deep cloning using deep serialization.
Pop Catalin
Unfortunately, not all objects are serializable either, so you can't always use that method either. Ian's link is the most comprehensive answer so far.
Burly
+78  A: 

Whilst the standard practice is to inherit from ICloneable (described here, so I wont regurgitate), here's a nice Deep Clone Object copier I found on codeproject a while ago and incorporated it in our stuff.

As mentioned above, it does require your objects to be Serializable

/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// 
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>

public static class ObjectCopier
{
    /// <summary>
    /// Perform a deep Copy of the object.
    /// </summary>
    /// <typeparam name="T">The type of object being copied.</typeparam>
    /// <param name="source">The object instance to copy.</param>
    /// <returns>The copied object.</returns>
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

    // Don't serialize a null object, simply return the default for that object
    if (Object.ReferenceEquals(source, null))
    {
        return default(T);
    }

    IFormatter formatter = new BinaryFormatter();
    Stream stream = new MemoryStream();
    using (stream)
    {
        formatter.Serialize(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}
}    

The idea behind it is that it serializes your object the deserializes it into a fresh object. The benefit is that you don't have to concern yourself about cloning everything when an object gets too complex.

EDIT

And with the use of extension methods (also from the originally referenced source):

In case you prefer to use the new Extension methods of C# 3.0, change the method to have the following signature:

   public static T Clone<T>(this T source)
   {
      ...
   }

Now the method call simply becomes objectBeingCloned.Clone();.

johnc
http://stackoverflow.com/questions/78536/cloning-objects-in-c/78551#78551 has a link to the code above [and references two other such implementations, one of which is more appropriate in my context]
Ruben Bartelink
Sorry not to have read the previous 78611 answers before offering perfectly valid and helpful advice
johnc
That is an excellent cloner. Bob.
scope_creep
Serialization/deserialization involves significant overhead that isn't necessary. See the ICloneable interface and .MemberWise() clone methods in C#.
David Lively
@David, granted, but if the objects are light, and the performance hit when using it is not too high for your requirements, then it is a useful tip. I haven't used it intensively with large amounts of data in a loop, I admit, but I have never seen a single performance concern.
johnc
@johnc I like your response because it'll work **almost** every time, but as an embedded systems guy, and mid-90's x86 assembly language graphics nut, optimization is always on my mind. Just remember that deserialization involves costly string processing and reflection, and that some property types - like Dictionaries - can't be serialized/deserialized. Still, very good response that I upvoted. ("Just remember" is for the peanut gallery).
David Lively
@David. I understand :)
johnc
+1 very nice thanks
m_oLogin
Very nice! Thank you very much.
Ioannis Karadimas
+11  A: 

The reason not to use ICloneable is not because it doesn't have a generic interface. The reason not to use it is because it's vague. It doesn't make clear whether you're getting a shallow or a deep copy; that's up to the implementer.

Yes, MemberwiseClone makes a shallow copy, but the opposite of MemberwiseClone isn't Clone; it would be, perhaps, DeepClone, which doesn't exist. When you use an object through its ICloneable interface, you can't know which kind of cloning the underlying object performs. (And XML comments won't make it clear, because you'll get the interface comments rather than the ones on the object's Clone method.)

What I usually do is simply make a Copy method that does exactly what I want.

Kyralessa
+1. Here's a good article on it by Brad Abrams- http://blogs.msdn.com/brada/archive/2004/05/03/125427.aspx
RichardOD
That's the same article the link in my answer points to.
Kyralessa
+1  A: 

I came up with this to overcome .net shortcoming having to manually deep copy List.

I use this:

static public IEnumerable<SpotPlacement> CloneList(List<SpotPlacement> spotPlacements)
{
    foreach (SpotPlacement sp in spotPlacements)
    {
        yield return (SpotPlacement)sp.Clone();
    }
}

And at another place:

public object Clone()
{
    OrderItem newOrderItem = new OrderItem();
    ...
    newOrderItem._exactPlacements.AddRange(SpotPlacement.CloneList(_exactPlacements));
    ...
    return newOrderItem;
}

I tried to come up with oneliner that does this, but it's not possible, due to yield not working inside anonymous method blocks.

EDIT:

Better still, use generic List cloner:

class Utility<T> where T : ICloneable
{
    static public IEnumerable<T> CloneList(List<T> tl)
    {
        foreach (T t in tl)
        {
            yield return (T)t.Clone();
        }
    }
}
Daniel Mošmondor
+2  A: 

Well I was having problems using ICloneable in Silverlight, but I liked the idea of seralization, I can seralize XML, so I did this:

 static public class SerializeHelper
{
  //Michael White, Holly Springs Consulting, 2009
  //[email protected]

    public static T DeserializeXML<T>(string xmlData)
        where T:new()
    {
        if (string.IsNullOrEmpty(xmlData))
            return default(T);

        TextReader tr = new StringReader(xmlData);

        T DocItms = new T();

        XmlSerializer xms = new XmlSerializer(DocItms.GetType());

        DocItms = (T)xms.Deserialize(tr);


        return DocItms == null ? default(T) : DocItms;


    }

    public static string SeralizeObjectToXML<T>(T xmlObject)
    {
        StringBuilder sbTR = new StringBuilder();

        XmlSerializer xmsTR = new XmlSerializer(xmlObject.GetType());

        XmlWriterSettings xwsTR = new XmlWriterSettings();

        XmlWriter xmwTR = XmlWriter.Create(sbTR, xwsTR);

        xmsTR.Serialize(xmwTR,xmlObject);

        return sbTR.ToString();

    }

    public static T CloneObject<T>(T objClone)
        where T:new()
    {

        string GetString = SerializeHelper.SeralizeObjectToXML<T>(objClone);

        return SerializeHelper.DeserializeXML<T>(GetString);

    }



}
Michael White
A: 

in order to run this example, you must add the following code:

using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.IO;

RCVS
It isn't really clear *which* example you mean, but assuming you mean the accepted answer - it isn't uncommon to not include the `using` directives, since the IDE can fill these in itself (right-click, resolve). When you have the necessary rep, this would have been better as a comment.
Marc Gravell
A: 

I've seen it implemented through reflection as well. Basically there was a method that would iterate through the members of an object and appropriately copy them to the new object. When it reached reference types or collections I think it did a recursive call on itself. Reflection is expensive, but it worked pretty well.

xr280xr