前提條件:從 一個變量到另一個變量按值復制對象,而不是按引用復制對象(即以與結構相同的方式復制)可能非常復雜。因為一個對象可能包含許多對象的引用,例如字段、成 員等,這將涉及許多煩人的處理操作。把每個成員從一個對象復制到另一個對象中可能不會成功,因為其中一些成員可能是引用類型。
淺復制:簡單地按照成員復制對象可以通過派生於System.Object的MemberwiseClone()方法來完成,這是一個受保護的方法,但是很容易在對象上定義一個調用該方法的公共方法。這個方法的復制功能成為淺復制。
淺復制的好處:不用引用對象類型。
淺復制的方法:
view sourceprint?01 using System;
02 using System.Collections.Generic;
03 using System.Text;
04
05 namespace ConsoleApplication2
06 {
07 public class Content
08 {
09 public int Val;
10 }
11
12 public class Cloner
13 {
14 public Content MyContent = new Content();
15 public Cloner(int newVal)
16 {
17 MyContent.Val = newVal;
18 }
19 public object GetCopy()
20 {
21 return MemberwiseClone();
22 }
23 }
24
25 public class Program
26 {
27 static void Main(string[] args)
28 {
29 Cloner mySource = new Cloner(5);
30 Cloner myTarget = (Cloner)mySource.GetCopy();
31 Console.WriteLine("MyTarget.MyContent.val = {0}",myTarget.MyContent.Val);
32 mySource.MyContent.Val = 2;
33 Console.WriteLine("MyTarget.MyContent.val = {0}", myTarget.MyContent.Val);
34 Console.ReadKey();
35 }
36 }
37 }
這裡的mySource.MyContent.Val = 2改變了該公共字段val的值,所以導致了生成結果如下:MyTarget.MyContent.val = 5MyTarget.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:ICloneable14 {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 #endregion35 }36 37 public class Program38 {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 既可作為深層副本實現,也可作為淺表副本實現。在深層副本中,所有的對象都是重復的;而在淺表副本中,只有頂級對象是重復的,並且頂級以下的對象包含引用。
結果克隆必須與原始實例具有相同的類型或是原始實例的兼容類型。