天天看點

C#系列——記一次業務需求:對象的深拷貝

 這篇随筆着實在意料之外,主要是源于上周開發BS的一個業務,需要用到對象的深拷貝。說的直白一點,就是将對象記憶體配置設定區和引用完全拷貝一份新的。這種需求以前就遇到過,怎麼解決的已經記不清了。這次趁着這個機會将對象的深拷貝這個知識點記錄下。

  先來說說業務場景,直接上代碼:

C#系列——記一次業務需求:對象的深拷貝
C#系列——記一次業務需求:對象的深拷貝

需求就是lstAttr變量儲存的是一個List<DragElementProp>類型的集合,需要周遊lstModel,需要将每一個的oModel的Name屬性的值賦給lstAttr執行個體的Value屬性。然後儲存多個lstAttr的集合,形如List<List<DragElementProp>>。通過上面的代碼在foreach (var oModel in lstModel)裡面每次new一個新的var lstResTmp = new List<DragElementProp>();來儲存指派後lstAttr,明眼人一看就知道這種方式肯定不行,因為C#裡面class是引用類型,每次改變的都是唯一的一個lstAttr執行個體,通過上面代碼的方式得到的lstRes肯定會是幾個相同的lstAttr,即最後一次指派的lstAttr。

  怎麼辦?各種百度、各種部落格園。查了多篇博文,發現答案千篇一律,深拷貝對象的三種解決方案:

實作ICloneable接口,自定義拷貝功能

序列化/反序列化類實作

通過反射實作

我們逐一看看這幾種方式

(1)實作ICloneable接口的方式,貼上園子裡面的代碼

C#系列——記一次業務需求:對象的深拷貝
C#系列——記一次業務需求:對象的深拷貝

很顯然,這種方式不可取。如果一個類裡面有多個其他類成員,那不是每個都要去定義這樣一個clone方法。太low。

(2)序列化反序列化方式。貼上園子裡面的代碼

C#系列——記一次業務需求:對象的深拷貝
C#系列——記一次業務需求:對象的深拷貝

這種方式比上面方式好一點,但是需要對象是可序列化的,即要加上[Serializable]特性标簽,部落客試過如果一個普通的類調用這個方法會報異常。

部落客用Newtonsoft.Json重新寫了個:

C#系列——記一次業務需求:對象的深拷貝
C#系列——記一次業務需求:對象的深拷貝

這種方式對對象沒什麼太特殊的要求。

(3)反射的方式,部落客自己簡單寫了一個:

C#系列——記一次業務需求:對象的深拷貝
C#系列——記一次業務需求:對象的深拷貝

這種方式也比較簡單,但考慮到反射得性能問題,而且如果是clone集合,需要周遊去反射這樣效率就更低。

  綜上所述:要深拷貝一個對象,其實上述無論哪種方式都是新産生一個對象,然後給新的對象依次指派來實作。方案一一般不可取,方案二在集合的序列化友善可能效率稍微高點,方案三如果隻是簡單的拷貝一個對象我覺得也是不錯的選擇。反正部落客更加偏好方案二,用起來簡單。

  

  反正找了好久說的都這三種方式,這次先記錄下,如果沒有更好的方式就用這些方案先解決吧,當然,如果以後知道了更好的方式也可以拿出來和大家分享。也不知道.Net是否預留了某些特殊的通道來處理這種深拷貝。希望知道的大俠多多指教~~

本文轉自懶得安分部落格園部落格,原文連結:http://www.cnblogs.com/landeanfen/p/4678534.html,如需轉載請自行聯系原作者