一般来说,我们总是想克隆一个引用类型和拷贝一个值类型。记住这点将有助于你解决调试时发生的错误。让我们更进一步分析并清理一下Dude类实现,使用ICloneable接口来代替CopyDude()方法。
public class Dude : ICloneable {
public string Name;
public Shoe RightShoe;
public Shoe LeftShoe;
public override string ToString () {
return (Name + " : Dude!, I have a " + RightShoe.Color +
" shoe on my right foot, and a " +
LeftShoe.Color + " on my left foot.");
}
#region ICloneable Members
public object Clone () {
Dude newPerson = new Dude();
newPerson.Name = Name.Clone() as string;
newPerson.LeftShoe = LeftShoe.Clone() as Shoe;
newPerson.RightShoe = RightShoe.Clone() as Shoe;
return newPerson;
}
#endregion
}
我们再来修改Main()中的方法:
public static void Main () {
Class1 pgm = new Class1();
Dude Bill = new Dude();
Bill.Name = "Bill";
Bill.LeftShoe = new Shoe();
Bill.RightShoe = new Shoe();
Bill.LeftShoe.Color = Bill.RightShoe.Color = "Blue";
Dude Ted = Bill.Clone() as Dude;
Ted.Name = "Ted";
Ted.LeftShoe.Color = Ted.RightShoe.Color = "Red";
Console.WriteLine(Bill.ToString());
Console.WriteLine(Ted.ToString());
}
最后,运行我们的程序,会得到如下的输出:
Bill : Dude!, I have a Blue shoe on my right foot, and a Blue on my left foot.
Ted : Dude!, I have a Red shoe on my right foot, and a Red on my left foot.
还有些比较有意思的东西,比如System.String重载的操作符=号就实现了clones方法,因此你不用过于担心string类的引用复制问题。但是你要注意内存的消耗问题。如果你仔细查看上图,由于string是引用类型所以需要一个指针指向堆中的另一个对象,但是看起来它像是一个值类型。