.net中有很多对象都实现了iclonable接口,这意味着它们能实现复制功能,比如说arraylist对象( 用c#描述数据结构3:arraylist),或自己编写实现了iclonable接口的对象。
查看ArrayList中关于Clone方法的介绍:
很好奇,浅表副本的概念,上msdn查阅后,解释的意思比较晦涩一点,浅表复制集合是指仅仅复制集合元素,不管元素是值类型还是引用类型,但是Clone并不会复制对象(引用指向的对象)。新Clone后的集合中,引用还是指向同一个对象(原来集合中引用指向的对象)。
一句话概括,Clone实现的所谓浅表副本,Clone出来的对象复制了值类型,复制了引用,而未复制引用对象。这个时候,可能就要问了,未复制引用对象是什么意思?通过代码是最好说明问题的,请看下面的代码,
//人员对象模型
public class Person
{ public string name { get; set; }
public ContactInfo description { get; set; }
public Person(string name, ContactInfo description)
{ this.description = description;
this.name = name;
}
} //联系信息对象
public class ContactInfo
{ public string address { get; set; }
public string telephone { get; set; }
public ContactInfo(string address, string telephone)
{
this.address = address;
this.telephone = telephone;
}
//跟新电话联系信息
public void UpdateTelephone(string telephone)
{
this.telephone = telephone;
}
}新建一个ArrayList对象,并分别添加为一个引用对象,一个值类型数据
//ArrayList对象
ArrayList arr1 = new ArrayList();
//Person对象创建,xiaoming引用Person对象
Person xiaoming = new Person("xiaoming",new ContactInfo("shanghai","18011113333"));
//arr1引用xiaoming,这样arr1[0]也引用了Person对象
arr1.Add(xiaoming);
//arr1中添加值类型整形5元素
arr1.Add(5);我们通过Clone接口,Clone出一个arr1的浅表副本:
ArrayList cloneArr1 = arr1.Clone() as ArrayList;
如图所示:

分别测试,克隆出来的实例cloneArr1都复制了什么,我们分别check下值类型和引用类型的复制情况。先看值类型的复制情况:
cloneArr1[1]=6;
我们检查下初始的集合arr1[1]的元素改变了吗?
未改变,值还是5,这说明,Clone后,值类型也复制出来,并且放到内存栈中。
Check下引用类型有没有重新从内存堆中重新开辟空间,修改xiaoming的联系-电话:
(cloneArr1[0] as Person).description.UpdateTelephone("170444455555"); 这个时候,我们再Check,初始集合arr1中xiaoming的联系方式改变了吗?
答案:改变了,和最新的170444455555一致。
这说明了对引用类型,浅表副本复制,只是复制引用,而未重新再内存堆中开辟内存空间。(如果您对内存堆,内存栈,概念不是很清楚,请参考我总结的:C#.NET:内存管理story-变量创建与销毁)。
至此,我们对Clone的功能有了一个全新的认识了!浅表副本,引用类型只复制引用,不复制对象。!
那么如果说,我想实现了深度复制呢,也就是我新复制出来的对象不是仅仅复制引用, 而是复制对象!比如说,你需要在一个模板的基础上修改出5个版本的建立,每个版本投递到不同的企业上,版本1投给公司A,版本2投给公司B,。。。假如说这5个版本的不同仅仅是“我期望加入某某公司”,某某换成5个公司对应的名称。
