首先描述一下拷貝的含義:拷貝就類似與復制,是為對象創建副本的技術。
c#中的拷貝分為深拷貝和淺拷貝。
淺拷貝:主要分為兩種情況來討論:值類型和引用類型。對於值類型來說:淺拷貝,拷貝的是對象的值。對於引用類型來說:拷貝的是對象的引用地址。
一般情況下都建議繼成ICloneable,顯示表明類型可以拷貝,具體如下:
public class TestClone : ICloneable { public int test { set; get; } public object Clone() { return this.MemberwiseClone(); } }
深拷貝:無論值類型還是引用類型,都是拷貝的對象的值。
深拷貝的實現方式:對於值類型來說,淺拷貝即是深拷貝。但是對於引用類型來說不一樣,所以我們這里討論的實現方式是對引用類型來說的。一般可以使用序列化,或者自定義方法,對每個對象進行復制。
注意:我們在淺拷貝時,對引用類型來說,拷貝的對象的引用,即舊對象的值改變,新對象的值也會改變,相反,新對象的值改變,舊對象的值也會改變。例如如下代碼:
public class TestClone : ICloneable { public string IDCard { set; get; } public bool testBool { set; get; } public List<int> testList { set; get; } public int test { set; get; } public object Clone() { return this.MemberwiseClone(); } } static void Main(string[] args) { TestClone cloneOld = new TestClone(); cloneOld.test = 1; cloneOld.testList = new List<int> { 1, 2 }; cloneOld.testBool = true; TestClone cloneNew = (TestClone)cloneOld.Clone(); Console.WriteLine(cloneOld.test); Console.WriteLine(cloneNew.test); Console.WriteLine(cloneOld.testList.Count); Console.WriteLine(cloneNew.testList.Count); Console.WriteLine(cloneOld.testBool); Console.WriteLine(cloneNew.testBool); Console.WriteLine("改變old的值"); cloneOld.test = 100; cloneOld.testList = new List<int> { 1, 2 ,3,4,5}; cloneOld.testBool = false; Console.WriteLine(cloneOld.test); Console.WriteLine(cloneNew.test); Console.WriteLine(cloneOld.testList.Count); Console.WriteLine(cloneOld.testList.Count); Console.WriteLine(cloneOld.testBool); Console.WriteLine(cloneNew.testBool); }
運行結果如下:
從以上結果可以看出:
引用類型中的值類型在淺拷貝時,是拷貝的是對象的值。
引用類型在淺拷貝時,拷貝的是對象的引用。
string類型的引用類型較為特殊,當淺拷貝時,是將對應的而引用拷貝給了新的對象,但是當舊對象的值發生改變時,新對象的值並不發生改變,因為在每次改變string的值是,都會創建一個新的string對象。即一旦創建了該string對象,就不能修改此對象的值了。