MSDN gives this example of a deep copy (http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx)
public class Person
{
public int Age;
The MemberwiseClone()
creates a new instance of the class being copied, and also copies scalar fields into the corresponding members of the copy. It provides a better starting point for deep copying than just a plain new
, because you need to "fix" only the items requiring deep copying.
MemberwiseClone does create a new object and copies all non static fields. In case of reference types this means copying the references. So yes, after a member wise clone the fields of the new object point to the same objects as the fields of the original object (for reference types). That is why the example in the MSDN create a new instance of the IdInfo
: To create a copy of that object as well.
Your DeepCopy
implementation is broken because it does not copy all fields, but if it would then the result would not be different from the MemberwiseClone
solution.
This question might also be an interesting read for you: Create a Deep Copy in C#
Alternatively, if you are able to set Serializable
attribute to all involved classes, you can use serialization. For the purpose of a generic deep copy I have this object
extension method:
public static class ObjectExtensions
{
#region Methods
public static T Copy<T>(this T source)
{
var isNotSerializable = !typeof(T).IsSerializable;
if (isNotSerializable)
throw new ArgumentException("The type must be serializable.", "source");
var sourceIsNull = ReferenceEquals(source, null);
if (sourceIsNull)
return default(T);
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
#endregion
}
This should also copy your IdInfo
field.
Usage is simple:
var copy = obj.Copy();
The implementation of MemberwiseClone
would do the following for your code.
Person p = new Person();
p.Age = this.Age; // value copy
p.Name = this.Name; // value copy
p.IdInfo = this.IdInfo; // reference copy. this object is the same in both coppies.
return p;
In the example that you specified, the values of Age and Name would be zero/blank.
This is due to the fact that you instantiate the Person object, but never set the values of these fields.
From Object.MemberwiseClone Method
The MemberwiseClone method creates a shallow copy by 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, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.
So as you can see, using the MemberwiseClone method, your Age/Name fields will also be copied/cloned.
Other alternative as object extension is the next:
public static class ObjectExtension
{
public static T Copy<T>(this T lObjSource)
{
T lObjCopy = (T)Activator.CreateInstance(typeof(T));
foreach (PropertyInfo lObjCopyProperty in lObjCopy.GetType().GetProperties())
{
lObjCopyProperty.SetValue
(
lObjCopy,
lObjSource.GetType().GetProperties().Where(x => x.Name == lObjCopyProperty.Name).FirstOrDefault().GetValue(lObjSource)
);
}
return lObjCopy;
}
}
For use:
User lObjUserCopy = lObjUser.Copy();