.NET对象克隆的深究(转)
今天在看.net設計模式(http://terrylee.cnblogs.com/archive/2006/01/16/317896.html)的時候,突然看到淺拷貝與深拷貝的一些細節,就想這兩者到底有什么區別呢,確實對此了解得不多,于是就上網找找資料,然后在csdn下看到了一篇這樣的文章,轉http://dev.csdn.net/develop/article/20/20324.shtm,這里貼出來讓也同樣不了解類似概念的大家看下是怎么回事:
簡介
本文我將討論.NET編程中一個比較感興趣的方面——對象克隆。下面將討論對象克隆的必要性、對象克隆的方法以及關于對象克隆的一些思考。
背景
大家一定知道.NET對象是有二大類型的:? 值類型和引用類型。 值類型對象的變量表示對象本身,而且具有“copy-on-assignment”的行為。也就是說, 以下的討論不適用于值類型。
另一方面,引用類型的變量實際上是指向堆上的內存。 因此,如果你創建了一個引用類型的變量,并且將一個已存在的對象分配給它,實際上是創建了指向堆上的相同內存的另外一個對象。本文就是討論這樣的情況:創建的一個對象的新的拷貝,并且保存在一個變量中!
為什么要克隆?
我 認為當設置一個對象的狀態要付出昂貴的代價,并且又需要取得該對象的一個拷貝以便改變當前的一些狀態時,克隆就顯得十分必要。下面列舉一個剛好能體現我剛 剛所說的情況的例子。 就拿 DataTable 類來說吧。建立一個 DataTable 會包含諸如以下的操作:為取得架構和數據而查詢數據庫、添加約束、設置主鍵等等。那么,當需要該 DataTable 的一個新的拷貝,哪怕是對架構作極小的改變或添加新的一行記錄等等, 明智的選擇會是克隆已存在的對象再對其進行操作,而不是創建一個新的DataTable, 那樣將需要更多的時間和資源。
克隆也廣泛應用于數組和集合,這些時候往往會多次需要已存在對象的一個拷貝。 克隆的類型我 們基于克隆的程度將克隆分成兩大類:“深層”克隆和“淺表”克隆。“淺表”克隆得到一個新的實例,一個與原始對象類型相同、包含值類型字段的拷貝。但是, 如果字段是引用類型的, 該引用將被拷貝, 而不是拷貝引用的對象。 因此,原始對象的引用和克隆對象的引用都指向同一個對象。另一方面, 對象的“深層”克隆包含原始對象直接或間接引用的對象的所有拷貝。下面舉例說明。
對象X引用對象A,對象A引用對象M。對象X的“淺表”克隆對象Y,同樣也引用了對象A。相對比的是,對象X的“深層”克隆對象Y,卻直接引用了對象B,并且間接引用對象N,這里,對象B是對象A的拷貝,對象N是對象M的拷貝。實現克隆
System.Object提供了受保護的方法 MemberwiseClone,可用來實現“淺表”克隆。由于該方法標記為“受保護”級別,因此,我們只能在繼承類或該類內部才能訪問該方法。
.NET定義了一個IClonable接口,一個需要“深層”克隆而不是“淺表”克隆的類必須實現該接口。我們需要提供一個好的實現方法來達到該接口的Clone方法實現的功能。
有 許多方法可以實現“深層”克隆。一個方法是將對象串行化到內存流中,然后反串行化到一個新的對象。我們將使用一個二進制(Binary)的 Formatter類或SOAP formatter類來進行深層串行化。做一個深寫成連載長篇而刊登的 formatter 。 這個方法的問題是類和它的成員 (完整的類表) 必須被標記為serializable,否則formatter會發生錯誤。
反射是另外一個能達到相同目的的方法。 Amir Harel寫的一篇好文章吸引了我, 他使用該方法提供一個好的克隆實現。 這篇文章討論得非常好! 以下是鏈接:http://www.codeproject.com/csharp/cloneimpl_class.asp
上面討論的任何一個方法,都要求對象的成員類型能支持自我克隆,以確保“深層”克隆能成功進行。也就是說, 對象必須是可串行化的(serializable) ,或者每個獨立的成員必須提供IClonable的實現。 如果不這樣,我們根本不可能對對象進行“深層”克隆!綜述
克隆是提供給程序員的一個很好的方 法。但是, 我們應該知道什么時候需要提供這樣的功能,而且在某些情況下,嚴格地說,對象不應該提供這一個特性。 以SQLTransaction 類為例, 就不支持克隆。這一個類代表了SQL Server數據庫的一個事務。 克隆該對象沒有任何意義,因為我們可能不能夠理解一個數據庫的一個活動的事務的克隆! 因此,如果你認為克隆對象的狀態會產生應用程序邏輯上的矛盾,就不需要支持克隆。
總結
以上是生活随笔為你收集整理的.NET对象克隆的深究(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 助学贷款续贷申请原因怎么写
- 下一篇: .Net与Oracle地数据库连接池(C