50

Let's say that I have a class:

class obj
{
  int a;
  int b;
}

and then I have this code:

obj myobj = new obj(){ a=1, b=2}
obj myobj2 = myobj;

Now the above code makes a reference to the first obj. What I want is that myobj2 refers to a copy of the myobj with changes not being reflected in the original. I have searched SO and the solutions thus far seems complicated. Is there an easier way to do this. I am using .net 4.5

Cœur
  • 37,241
  • 25
  • 195
  • 267
Win Coder
  • 6,628
  • 11
  • 54
  • 81

2 Answers2

100

Properties in your object are value types and you can use the shallow copy in such a situation like that:

obj myobj2 = (obj)myobj.MemberwiseClone();

But in other situations, like if any members are reference types, then you need Deep Copy. You can get a deep copy of an object using Serialization and Deserialization techniques with the help of BinaryFormatter class:

public static T DeepCopy<T>(T other)
{
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Context = new StreamingContext(StreamingContextStates.Clone);
        formatter.Serialize(ms, other);
        ms.Position = 0;
        return (T)formatter.Deserialize(ms);
    }
}

The purpose of setting StreamingContext: We can introduce special serialization and deserialization logic to our code with the help of either implementing ISerializable interface or using built-in attributes like OnDeserialized, OnDeserializing, OnSerializing, OnSerialized. In all cases StreamingContext will be passed as an argument to the methods(and to the special constructor in case of ISerializable interface). With setting ContextState to Clone, we are just giving a hint to that method about the purpose of the serialization.

Additional Info: (you can also read this article from MSDN)

Shallow copying is creating a new object and then copying the nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field is performed; for a reference type, the reference is copied but the referred object is not; therefore the original object and its clone refer to the same object.

Deep copy is creating a new object and then copying the nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, a new copy of the referred object is performed.

Farhad Jabiyev
  • 26,014
  • 8
  • 72
  • 98
  • 4
    This answer [has already been proposed](http://stackoverflow.com/a/78612/211627). It works under certain conditions, but as noted previously, it will fail in a Medium Trust environment or if certain properties are not serializable (such as Dictionaries). It also requires a LOT of overhead, so it will cause a noticeable slowdown under the right conditions. Use with caution - it may make your code difficult to maintain. +1 for the additional info, though. – JDB May 22 '13 at 16:43
  • 2
    Thank you! I have to note that the coping object and all its sub objects should be marked like `[Serializable]`. – NoWar Oct 01 '14 at 18:43
9

You can use MemberwiseClone

obj myobj2 = (obj)myobj.MemberwiseClone();

The copy is a shallow copy which means the reference properties in the clone are pointing to the same values as the original object but that shouldn't be an issue in your case as the properties in obj are of value types.

If you own the source code, you can also implement ICloneable

vc 74
  • 37,131
  • 7
  • 73
  • 89
  • 4
    This works for simple objects. For more complicated types, you may need to implement your own field-by-field copy, especially if any members are themselves reference types. – Joel Coehoorn May 22 '13 at 16:03
  • 3
    Why would I NOT be able to call .MemberwiseClone() on my object? Surely all objects inherit from Object and therefore should have this function? It says it's not a method. Does it only work on certain types of object? – NickG Jun 12 '14 at 08:40
  • 2
    @NickG The method is defined on `Object` and so exists in any class/struct. However, the method is `protected`. For that reason, you can call `expression.MemberwiseClone()` if the class you are inside is, or derives from, the type of `expression`. For example in the above answer, `myobj` is the expression, and it has type `obj`, so you can only call `MemberwiseClone` on it if you are inside the class `obj` or inside a class deriving from `obj`. – Jeppe Stig Nielsen Jan 16 '16 at 17:20
  • 4
    That should have been: _...if you are inside the class `obj` or inside a class from which `obj` derives._ – Jeppe Stig Nielsen Jan 16 '16 at 17:29