.NET物件克隆的深究 (轉)

amyz發表於2007-11-12
.NET物件克隆的深究 (轉)[@more@]

By ?id=144339">Manoj G :namespace prefix = o ns = "urn:schemas--com::office" />

Posted 1 Aug

Applied to:

, XP, W2K, 1.1,

摘要:本文討論了為什麼需要的克隆,怎樣克隆以及對克隆的一些思考。

files - 10 Kb

簡介

本文我將討論.NET中一個比較感興趣的方面——物件克隆。下面將討論物件克隆的必要性、物件克隆的方法以及關於物件克隆的一些思考。

背景

大家一定知道.NET物件是有二大型別的:  值型別和引用型別。 值型別物件的變數表示物件本身,而且具有“copy-on-assignment”的行為。也就是說, 以下的討論不適用於值型別。 

另一方面,引用型別的變數實際上是指向堆上的。 因此,如果你建立了一個引用型別的變數,並且將一個已存在的物件分配給它,實際上是建立了指向堆上的相同記憶體的另外一個物件。本文就是討論這樣的情況:建立的一個物件的新的複製,並且儲存在一個變數中! 

為什麼要克隆?

我認為當設定一個物件的狀態要付出昂貴的代價,並且又需要取得該物件的一個複製以便改變當前的一些狀態時,克隆就顯得十分必要。下面列舉一個剛好能體現我剛剛所說的情況的例子。 就拿 DataTable 類來說吧。建立一個 DataTable 會包含諸如以下的操作:為取得架構和資料而查詢、新增、設定主鍵等等。那麼,當需要該 DataTable 的一個新的複製,哪怕是對架構作極小的改變或新增新的一行記錄等等, 明智的選擇會是克隆已存在的物件再對其進行操作,而不是建立一個新的DataTable, 那樣將需要更多的時間和資源。 

克隆也廣泛應用於陣列和集合,這些時候往往會多次需要已存在物件的一個複製。 

克隆的型別

我們基於克隆的程度將克隆分成兩大類:“深層”克隆和“淺表”克隆。“淺表”克隆得到一個新的例項,一個與原始物件型別相同、包含值型別欄位的複製。但是,如果欄位是引用型別的, 該引用將被複製, 而不是複製引用的物件。 因此,原始物件的引用和克隆物件的引用都指向同一個物件。另一方面, 物件的“深層”克隆包含原始物件直接或間接引用的物件的所有複製。下面舉例說明。

兩種克隆a模式的比較 hspace=0 src="/Develop/ArticleImages/20/20324/CSDN_Dev_Image_2003-8-81651000.jpg" align=baseline border=0>

物件X引用物件A,物件A引用物件M。物件X的“淺表”克隆物件Y,同樣也引用了物件A。相對比的是,物件X的“深層”克隆物件Y,卻直接引用了物件B,並且間接引用物件N,這裡,物件B是物件A的複製,物件N是物件M的複製。

實現克隆

System.提供了受保護的方法 MemberwiseClone,可用來實現“淺表”克隆。由於該方法標記為“受保護”級別,因此,我們只能在繼承類或該類內部才能訪問該方法。

.NET定義了一個IClonable介面,一個需要“深層”克隆而不是“淺表”克隆的類必須實現該介面。我們需要提供一個好的實現方法來達到該介面的Clone方法實現的功能。

有許多方法可以實現“深層”克隆。一個方法是將物件化到記憶體流中,然後反序列化到一個新的物件。我們將使用一個二進位制(Binary)的 Formatter類或P formatter類來進行深層序列化。做一個深寫成連載長篇而刊登的 formatter 。 這個方法的問題是類和它的成員 (完整的類表) 必須被標記為serializable,否則formatter會發生錯誤。 

反射是另外一個能達到相同目的的方法。 Amir Harel寫的一篇好文章吸引了我, 他使用該方法提供一個好的克隆實現。 這篇文章討論得非常好! 以下是連結:

/cloneimpl_class.asp">

上面討論的任何一個方法,都要求物件的成員型別能支援自我克隆,以確保“深層”克隆能成功進行。也就是說, 物件必須是可序列化的(serializable) ,或者每個獨立的成員必須提供IClonable的實現。 如果不這樣,我們根本不可能對物件進行“深層”克隆!

綜述

克隆是提供給員的一個很好的方法。但是, 我們應該知道什麼時候需要提供這樣的功能,而且在某些情況下,嚴格地說,物件不應該提供這一個特性。 以Transaction 類為例, 就不支援克隆。這一個類代表了資料庫的一個事務。 克隆該物件沒有任何意義,因為我們可能不能夠理解一個資料庫的一個活動的事務的克隆! 因此,如果你認為克隆物件的狀態會產生應用程式邏輯上的矛盾,就不需要支援克隆。

 

  (完)

 

參看原文:

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-981977/,如需轉載,請註明出處,否則將追究法律責任。

相關文章