For creating shallow copies, the C# Clone method and ICloneable
interface
are available, but using these features causes confusion.
Usually avoiding Clone()
is a good plan—it is clearer just to copy fields when necessary, as with Array.Copy
or assignment.
This program uses Clone()
on a string
array. The Array type implements ICloneable
and the Clone call results in a copied array.
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
In the implementation of Clone, the Array.Clone
static
method is called. And Array.Clone
calls into MemberwiseClone
. Remember that System.Array
implements System.ICloneable
.
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
ICloneable
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.
class
with its public constructor. We pass 3 arguments to it.Console.WriteLine
—this calls To String
.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
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.
We explored Clone()
and the ICloneable
interface
. It is difficult to use this interface
correctly—using custom methods is clearer.