Sample source code
Shallow Copy and Deep Copy
When creating a copy of an object in memory, the type of copy can be described as either a shallow copy or a deep copy. The Object class defines the MemberwiseClone method, which performs a bit by bit copy of an object’s value type members. In the case of reference type members the MemberwiseClone method will create a copy of the reference, but not a copy of the object being referenced. Creating a copy of an object using the MemberwiseClone method will thus result in copies and the original object still referencing the same member object in memory when that object is a reference type. The MemberwiseClone method performs a shallow copy when invoked.
A deep copy of an object results in copies and the original object not referencing the same reference type member object in memory.
Example custom data type
The sample source code provided with this article provides a user defined data type, the CustomDataType class of which the code snippet is listed below.
Notice that the CustomDataType class definition is marked with the Serializable attribute. Objects of which the type definition is not marked with the Serializable attribute cannot be serialized. Trying to perform serialization on objects not marked as Serializable will result in an exception being thrown.
The DeepCopy method – Implementation as an extension method with generic type support
Extension method architecture enables developers to create methods which, from a syntactic and implementation point of view appear to be part of an existing data type. Extension methods create the perception of being updates or additions, literarily extending a data type as the name implies. Extension methods do not require access to the source code of the particular types being extended, nor does the implementation thereof require recompilation of the referenced types.
DeepCopy additionally defines the generic type <T> which determines the return value’s type and the type of the parameter objectToCopy.
The method body creates an instance of a MemoryStream object and an object instance of type BinaryFormatter. When BinaryFormatter.Serialize is invoked the byte representation of the objectToCopy parameter is written to the specified MemoryStream. In a similar fashion BinaryFormatter.Deserialize is invoked next, reading the byte representation from the specified MemoryStream. The object returned is cast to the same type as the object originally serialized.
The DeepCopy method illustrated above appears as a member method to the CustomDataType class created earlier.
The code snippet listed above is a console application which implements the DeepCopy extension method on objects of type CustomDataType. Modifying the member properties of the second object instance will not result in the first object instance properties being modified.