Sample source code
This article is accompanied by a sample source code Visual Studio project which is available for download here.
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.
This article is a follow up article on: C# How to: Deep copy objects using Binary Serialization. When using Binary Serialization objects being serialized have to be decorated with any number of attributes which aid serialization and deserialization. An object’s definition has to at the very least specify the Serializable attribute, if not attempting serialization results in a runtime exception.
The advantage of implementing deep copy operations by making use of a NetDataContractSerializer can be argued around not having to specify serialization attributes. Although, as is the case with binary serialization, only objects that define a default/parameter less public constructor can be serialized without specifying any additional attributes.
Example custom data type
The code snippet listed below illustrates several user/custom defined data types. Notice the complete absence of any code attributes, as usually required for successful serialization/deserialization. Also pay attention to the private member variables, being an enum and user defined reference type defined towards the end of this snippet.
For the sake of convenience I overload the ToString() method, returning a string representation of an object’s member values.
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 NetDataContractSerializer. When the Serialize method is invoked the Xml representation of the objectToCopy parameter is written to the specified MemoryStream. In a similar fashion Deserialize is invoked next, reading the Xml representation from the specified MemoryStream. The object returned is cast to the same type as the object originally serialized.
Note: From MSDN documentation:
Serializes and deserializes an instance of a type into XML stream or document using the supplied .NET Framework types.
The NetDataContractSerializer differs from the DataContractSerializer in one important way: the NetDataContractSerializer includes CLR type information in the serialized XML, whereas the DataContractSerializer does not. Therefore, the NetDataContractSerializer can be used only if both the serializing and deserializing ends share the same CLR types.
In the scenario illustrated it can be considered safe to use NetDataContractSerializer since objects being serialized are only persisted to memory for a few milliseconds and then deserialized back to an object instance.
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.