前提條件:從
一個變數到另一個變數按值複製對象,而不是按引用複製對象(即以與結構相同的方式複製)可能非常複雜。因為一個對象可能包含許多個物件的引用,例如欄位、成
員等,這將涉及許多煩人的處理操作。把每個成員從一個對象複製到另一個對象中可能不會成功,因為其中一些成員可能是參考型別。
淺複製:簡單地按照成員複製對象可以通過派生於System.Object的MemberwiseClone()方法來完成,這是一個受保護的方法,但是很容易在對象上定義一個調用該方法的公用方法。這個方法的複製功能成為淺複製。
淺複製的好處:不用引用物件類型。
淺複製的方法:
using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication2{ public class Content { public int Val; } public class Cloner { public Content MyContent = new Content(); public Cloner(int newVal) { MyContent.Val = newVal; } public object GetCopy() { return MemberwiseClone(); } } public class Program { static void Main(string[] args) { Cloner mySource = new Cloner(5); Cloner myTarget = (Cloner)mySource.GetCopy(); Console.WriteLine("MyTarget.MyContent.val = {0}",myTarget.MyContent.Val); mySource.MyContent.Val = 2; Console.WriteLine("MyTarget.MyContent.val = {0}", myTarget.MyContent.Val); Console.ReadKey(); } }}
這裡的mySource.MyContent.Val = 2改變了該公用欄位val的值,所以導致了產生結果如下:
MyTarget.MyContent.val = 5
MyTarget.MyContent.val = 2
上面通過複製參考型別來體現了淺度複製的使用方法。
如果想要使產生的值都為5,就需要使用深度複製.關於深度複製:使用深度複製,必須使類實現ICloneable介面,該介面有一個方法Clone(),這個方法不帶參數,返回一個物件類型, 其簽名和上面使用的GetCopy()方法相同。
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace ConsoleApplication2
6 {
7 public class Content
8 {
9 public int Val;
10
11 }
12
13 public class Cloner:ICloneable
14 {
15 public Content MyContent = new Content();
16
17 public Cloner(int newVal)
18 {
19 MyContent.Val = newVal;
20 }
21 public object GetCopy()
22 {
23 return MemberwiseClone();
24 }
25
26 #region ICloneable 成員
27
28 public object Clone()
29 {
30 Cloner clonedCloner = new Cloner(MyContent.Val);
31 return clonedCloner;
32 }
33
34 #endregion
35 }
36
37 public class Program
38 {
39 static void Main(string[] args)
40 {
41 Cloner mySource = new Cloner(5);
42 Cloner myTarget = (Cloner)mySource.Clone();
43 Console.WriteLine("MyTarget.MyContent.val = {0}",myTarget.MyContent.Val);
44 mySource.MyContent.Val = 2;
45 Console.WriteLine("MyTarget.MyContent.val = {0}", myTarget.MyContent.Val);
46 Console.ReadKey();
47 }
48 }
49 }
因為在將Cloner實現ICloneable時使用了深度複製,來建立了作為當前執行個體(這裡指clonedCloner)副本的新對象,最後在測試深度複製時,又調用了Clone()的方法,而沒有調用GetCopy()方法,所以導致了myTarget.MyContent.Val的值一直是new Cloner(5),而不是在最後定義的值2.經過這個知識點的學習,我認為ICloneable()介面的存在就是為了調用clone()方法的,如果需要將某個參考型別或者實值型別的值直接複製給對象,就直接讓其實現該介面的方法,這個可能理解的不正確,希望大家和我交流。關於ICloneable()介面的Clone()方法的說明:Clone 既可作為深層副本實現,也可作為淺表副本實現。在深層副本中,所有的對象都是重複的;而在淺表副本中,只有頂級對象是重複的,並且頂級以下的對象包含引用。結果複製必須與原始執行個體具有相同的類型或是原始執行個體的相容類型。