.NET中有很多個物件都實現了IClonable介面,這意味著它們能實現複製功能,比如說ArrayList對象( 用C#描述資料結構3:ArrayList),或自己編寫實現了IClonable介面的對象。
查看ArrayList中關於Clone方法的介紹:
建立 System.Collections.ArrayList 的淺表副本。
很好奇,淺表副本的概念,上msdn查閱後,解釋的意思比較晦澀一點,淺層複製 (Shallow Copy)集合是指僅僅複製集合元素,不管元素是實值型別還是參考型別,但是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;
:
分別測試,複製出來的執行個體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個公司對應的名稱。