ICloneable接口使得实现该接口的类可以自定义Clone()方法,一般情况下,会调用Object类的MemberwiseClone()方法来实现克隆一个浅表副本。
按照MSDN的说法,所谓浅表副本就是生成一个和源对象相同的新对象,但是该对象中顶级(类的直接成员)成员实现拷贝,而其他类的其他对象则为对象的引用,即源对象和克隆对象指向同一个位置。
class CloneClass:ICloneable
{
public string CloneString { get; set; }
public InnerClass InnerObject { get; set; }
public CloneClass()
{
InnerObject = new InnerClass();
}
public object Clone()
{
return this.MemberwiseClone();
}
}
class InnerClass
{
public string Id { get; set; }
public string Content { get; set; }
public InnerClass(string Id = "", string Content = "")
{
this.Id = Id;
this.Content = Content;
}
}
运行一下
static void Main(string[] args)
{
CloneClass A = new CloneClass();
A.CloneString = "abcabc";
CloneClass B = (CloneClass)A.Clone();
Console.WriteLine(B.CloneString);
B.CloneString = "cbacba";
Console.WriteLine(B.CloneString);
Console.WriteLine(A.CloneString);
Console.WriteLine(B.InnerObject.GetHashCode());
Console.WriteLine(A.InnerObject.GetHashCode());
Console.WriteLine(B.GetHashCode());
Console.WriteLine(A.GetHashCode());
Console.ReadLine();
}
运行结果其实就是:
通过运行结果我们可以看到,该浅表副本中,CloneString对象是互为副本的。通过比较A和B对象自身的HashCode发现两者是两个不同的对象,但是A和B内的InnerObject对象的HashCode相同则说明这两个对象实为一个对象。
如果将上述代码中的Clone()方法改一下,自己实现其中的部分逻辑:
public object Clone()
{
CloneClass tempo = (CloneClass)this.MemberwiseClone();
tempo.InnerObject = new InnerClass();
return tempo;
}
再次运行后
发现由于由于new了一个新的InnerObject,A和B的InnerObjectHashCode发生了变化。则说明该代码自己实现了深层克隆。但是如果每个成员变量都需要自己实现深层克隆则代价较大。