Home
C#
Clone Examples
This page was last reviewed on May 21, 2023.
Dot Net Perls
Clone. For creating shallow copies, the C# Clone method and ICloneable interface are available. But using these features causes confusion.
C# Clone warning. Usually avoiding Clone() is a good plan. It is clearer just to copy fields when necessary, as with Array.Copy or assignment.
Array.Copy
Example. This program uses Clone() on a string array. The Array type implements ICloneable and the Clone call results in a copied array.
Array
interface
Info When we change the cloned array, the original is unchanged. We use a cast to change the type of the object returned by Clone.
as
using System; string[] array = { "a", "b", "c" }; string[] cloned = array.Clone() as string[]; Console.WriteLine(string.Join(",", array)); Console.WriteLine(string.Join(",", cloned)); Console.WriteLine(); // Change the first element in the cloned array. cloned[0] = "?"; Console.WriteLine(string.Join(",", array)); Console.WriteLine(string.Join(",", cloned));
a,b,c a,b,c a,b,c ?,b,c
Example 2. Next we consider the implementation of Clone. The Array.Clone static method is called. And internally Array.Clone calls into MemberwiseClone.
Also System.Array implements System.ICloneable. This is how the runtime knows to pass a call to Clone to the System.Array type.
IL_0022: callvirt instance object [mscorlib]System.Array::Clone()
IL_0001: call instance object System.Object::MemberwiseClone()
.method public hidebysig newslot abstract virtual instance object Clone() cil managed { } // end of method ICloneable::Clone
Example 3. The Rock class implements ICloneable, and defines the Clone() public method. This is probably not "good" code, but if Clone is wanted for some reason, it will work.
Next We create a new instance of the Rock class with its public constructor. We pass three arguments to it.
Constructor
Finally We invoke the Clone method on the first Rock instance and cast its result. We call Console.WriteLine—this calls To String.
Console.WriteLine
ToString
using System; class Rock : ICloneable { int _weight; bool _round; bool _mossy; public Rock(int weight, bool round, bool mossy) { this._weight = weight; this._round = round; this._mossy = mossy; } public object Clone() { return new Rock(this._weight, this._round, this._mossy); } public override string ToString() { return string.Format("weight = {0}, round = {1}, mossy = {2}", this._weight, this._round, this._mossy); } } class Program { static void Main() { Rock rock1 = new Rock(10, true, false); Rock rock2 = rock1.Clone() as Rock; Console.WriteLine("1. {0}", rock1); Console.WriteLine("2. {0}", rock2); } }
1. weight = 10, round = True, mossy = False 2. weight = 10, round = True, mossy = False
Discussion. Clone has some problems. The main issue is the question of shallow and deep copies. ICloneable does not define which kind of cloning is done.
So The developers using Clone are left guessing. This works against the whole point of interfaces, which is to define contracts.
A summary. We explored Clone() and the ICloneable interface. It is difficult to use this interface correctly—using custom methods is clearer.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on May 21, 2023 (simplify).
Home
Changes
© 2007-2024 Sam Allen.