程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 淺談C#淺拷貝和深拷貝

淺談C#淺拷貝和深拷貝

編輯:C#入門知識

從今天開始,我將每天和大家分享這本書中的內容,並加上自己的理解,希望可以幫助到更多和我一樣盲目的程序員們。   今天我們談談C#中的對象拷貝問題;   所謂的對象拷貝,其實就是為對象創建副本,C#中將拷貝分為兩種,分別為淺拷貝和深拷貝;   所謂淺拷貝就是將對象中的所有字段復制到新的副本對象中;淺拷貝對於值類型與引用類型的方式有區別,值類型字段的值被復制到副本中後,在副本中的修改不會影響源對象對應的值;然而對於引用類型的字段被復制到副本中的卻是引用類型的引用,而不是引用的對象,在副本中對引用類型的字段值被修改後,源對象的值也將被修改。   深拷貝也同樣是將對象中的所有字段復制到副本對象中,但是,無論對象的值類型字段或者引用類型字段,都會被重新創建並復制,對於副本的修改,不會影響到源對象的本身;   當然,無論是哪種拷貝,微軟都建議使用類型繼承ICloneable接口的方式明確告訴調用者,該對象是否可用被拷貝。當然了,ICloneable接口只提供了一個聲明為Clone的方法,我們可以根據需求在Clone的方法內實現淺拷貝或者是深拷貝,下面我們進行一段淺拷貝的案例,代碼如下     復制代碼  1     class Student : ICloneable  2     {  3         public string IDCode { get; set; }  4   5         public int Age { get; set; }  6   7         public Grent Grent { get; set; }  8   9         #region 拷貝主體 10         public object Clone() 11         { 12             return this.MemberwiseClone(); 13             //throw new NotImplementedException(); 14         } 15         #endregion 16  17     } 18  19     class Grent 20     { 21         public string Name { get; set; } 22  23         public override string ToString() 24         { 25             return this.Name; 26         } 27     } 復制代碼 調用     復制代碼 Student stu1 = new Student()             {                 IDCode = "lily",                 Age = 24,                 Grent = new Grent() { Name="五年三班"}             };             Student stu2 = stu1.Clone() as Student;             if (stu2 == null) {                 Console.WriteLine("轉換失敗");                 Console.ReadKey();                 return;             }               Console.WriteLine(stu2.IDCode);             Console.WriteLine(stu2.Age);             Console.WriteLine(stu2.Grent.ToString());               Console.WriteLine("重新為stu1賦值");             stu1.IDCode = "Anagle";             stu1.Age += 10;             stu1.Grent.Name = "六年二班";             Console.WriteLine(stu2.IDCode);             Console.WriteLine(stu2.Age);             Console.WriteLine(stu2.Grent.ToString());             Console.ReadKey(); 復制代碼 輸出結果為:   lily   24   五年三班   重新為stu1賦值   lily   24   六年二班           這裡我們需要注意一點Student中的IDCode屬性是string類型,理論上string類型是引用類型,但是由於該引用類型的特殊性,Object.MemberwiseClone方法仍舊為他創建了副本,也就是說,在淺拷貝過程中,我們應該將字符串看成值類型;   因為Student中的Grent是引用類型,所以在stu1中的Grent的Name被改變的同時,副本stu2中的Grent的Name也同樣被改變。   Student的深拷貝有多鐘實現方法,最簡單的方法是手動對字段诼個賦值,但是這種方法容易出錯,也就是說,如果類型的字段發生變化或有增減時,那麼該拷貝方法也就要發生相應的變化,所以,建議使用序列化的形式來進行深拷貝。實現代碼如下     復制代碼     [Serializable]     class Student : ICloneable     {         public string IDCode { get; set; }           public int Age { get; set; }           public Grent Grent { get; set; }           #region 拷貝主體         /// <summary>         /// 深度拷貝         /// </summary>         /// <returns></returns>         public Student DeepClone() {             using (Stream objectStream = new MemoryStream()) {                 IFormatter formatter = new BinaryFormatter();                 formatter.Serialize(objectStream, this);                 objectStream.Seek(0,SeekOrigin.Begin);                 return formatter.Deserialize(objectStream) as Student;             }         }           public object Clone()         {             return this.MemberwiseClone();         }         #endregion       } 復制代碼 調用DeepClone方法     復制代碼 Student stu1 = new Student()             {                 IDCode = "lily",                 Age = 24,                 Grent = new Grent() { Name="五年三班"}             };             Student stu2 = stu1.DeepClone() as Student;             if (stu2 == null) {                 Console.WriteLine("轉換失敗");                 Console.ReadKey();                 return;             }               Console.WriteLine(stu2.IDCode);             Console.WriteLine(stu2.Age);             Console.WriteLine(stu2.Grent.ToString());               Console.WriteLine("重新為stu1賦值");             stu1.IDCode = "Anagle";             stu1.Age += 10;             stu1.Grent.Name = "六年二班";             Console.WriteLine(stu2.IDCode);             Console.WriteLine(stu2.Age);             Console.WriteLine(stu2.Grent.ToString());             Console.ReadKey(); 復制代碼 輸出結果為:   lily   24   五年三班   重新為stu1賦值   lily   24   五年三班

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved