作者:vuefine 文献:msdn 平台:.NET 2.0+
.NET中有很多对象都实现了IClonable接口,这意味着它们能实现复制功能,比如说ArrayList对象( 用C#描述数据结构3:ArrayList),或自己编写实现了IClonable接口的对象。
查看ArrayList中关于Clone方法的介绍:
创建 System.Collections.ArrayList 的浅表副本。
很好奇,浅表副本的概念,上msdn查阅后,解释的意思比较晦涩一点,浅表复制集合是指仅仅复制集合元素,不管元素是值类型还是引用类型,但是Clone并不会复制对象(引用指向的对象)。新Clone后的集合中,引用还是指向同一个对象(原来集合中引用指向的对象)。
A shallow copy of a collection copies only the elements of the collection, whether they are reference types or value types, but it does not copy the objects that the references refer to. The references in the new collection point to the same objects that the references in the original collection point to.
一句话概括,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;如图所示:
我们检查下初始的集合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个公司对应的名称。
请参考我总结的文章:如何由浅复制到深复制?
我测试的源码下载地址: http://download.csdn.net/detail/daigualu/9772853
新闻热点
疑难解答