ICloneable.Clone Method
Creates a new object that is a copy of the current instance.
Assembly: mscorlib (in mscorlib.dll)
Clone can be implemented either as a deep copy or a shallow copy. In a deep copy, all objects are duplicated; whereas, in a shallow copy, only the top-level objects are duplicated and the lower levels contain references.
The resulting clone must be of the same type as or a compatible type to the original instance.
Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98, Windows CE, Windows Mobile for Smartphone, Windows Mobile for Pocket PC, Xbox 360, Zune
The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
The difficulty in fact is exactly similar to the problem of serialization: a deep, but safe, cloning operation that maintains the graph of references and its topology without duplicating the new objects, and maintaining the number of internal references in the deep copy, requires tracking, throughout the recursive operations, the current state of source objects that have already been cloned: this basically requires maintaining a hashed dictionary structure where you'll map the source objects to the newly allocated ones that have already been cloned in a shallow way, and to use an internal recursion: no object can be removed from this map that will be filled progressively while traversing the references.
A simple deep clone operation can then serialize the object and deserialize it in a new separate context (which will be empty at start of the operation). You don't necessarily need to serialize all fields, given that they will be constructed and updated during the recursion.
For this reason, a Clone() operation on an object that is not serializable, should just be shallow, and a Clone() operation on a serializable object should be deep and make use of the serialization mechanism, in order to be consistant, and all the efforts should preferably be made in the serialization and deserialization code. There are design patterns to allow this. Applications using Clone() should never assume that the new objects will be fully detached from the original though deeper references than just the first-level members, except if they have the semantic of values. All reference members should then be assumed to have not been cloned themselves.
It is then suggested that Clone() only performs a shallow copy in ALL cases, and that another interface should be used for deep cloning through consistant serialization: this operation for deep cloning will need another parameter for the current context, and this should be a dictionary map of objects that have already been cloned or serialized. If the various references have known object types, this can be implemented directly.
But a default operation deep cloning operation should be provided by the CLR for serializable objects, that could use Reflection to get the list of members that are attributed as serializable (this should include all members that have the semantic of values like structures and native value types or enums, plus only those members that have the semantic of references AND that are NOT weak references AND that are specificially marked as serializable, and then construct all objects in a consistant way through their deserialization constructors (which may be protected or sometimes even private...). The updated map needs only to record the reference objects, not the value objects.
Note the difference between .Net and Java environments : .Net uses an explicit "[NonSerialized()]" attribute to mark the reference members (or value types or even WeakReferences) that do not need to be serialized; Java uses the "@Serial" annotation to mark explicitly only the members that need to be serialized. The defaults are different. But both environments do not provide a simple design pattern for deep cloning through serialization attributes and from other simples rules (such as not serializing weak references, and serializing by default all the value types). The default Clone() operation on Cloneable objects performs a shallow copy but it will be inconsistant it it duplicates the weakreferences or internal value types that are just needed for internal operations such as those that control the synchronization.