C# 實現一個對象的深複製的方法

首先解釋下深複製和淺複製的區別:
淺複製:A對象複製後成B對象,A對象中還有成員或者子成員與B對象的成員或者子成員指向同一個內存地址,也就是A和B是不同的對象,但是操作B對象,可能會影響改變A對象
深複製:A對象賦值成B對象後,A和B無任何瓜葛,操作B對象不會對A對象產生任何影響。
用代碼來說明下平時寫代碼的深淺複製:
淺複製:

 public class Test
 {
      public string A { get; set; }
      public int B { get; set; }
      public override string ToString()
      {
          return $"A:{A},B:{B}";
      }
 }
    static void Main(string[] args)
	  {
	         var list = new List<Test>()
	         {
	             new Test(){A="A1",B=1 },
	             new Test(){ A="A2",B=2}
	         };
	         var list_Copy = list.ToList();
	         list_Copy[0].A = "這是修改後的值";
	         foreach (var i in list)
	         {
	             Console.WriteLine(i);
	         }
	         Console.Read();
	  }

執行結果如下:
在這裏插入圖片描述
從結果可以看到,修改list_Copy的元素的屬性值,list中的元素的屬性也跟着變了。
深複製,我們使用C#自帶的克隆模式來實現:

 public class Test:ICloneable
    {
        public string A { get; set; }
        public int B { get; set; }

        public object Clone()
        {
            return this.MemberwiseClone();
        }

        public override string ToString()
        {
            return $"A:{A},B:{B}";
        }
    }
    static void Main(string[] args)
        {
            var list = new List<Test>()
            {
                new Test(){A="A1",B=1 },
                new Test(){ A="A2",B=2}
            };
            var list_Copy = new List<Test>();
            list.ForEach(x => list_Copy.Add(x.Clone() as Test));
            list_Copy[0].A = "這是修改後的值";
            foreach (var i in list)
            {
                Console.WriteLine(i);
            }
            Console.Read();
        }

執行結果如下:
在這裏插入圖片描述
可以看到,修改list_Copy的任何元素任何屬性,都不會影響到list,但是list與list_Copy中的元素值是相同的,這就是深複製
我們平時寫軟件,有時候會用到深複製,下面介紹實現深複製的幾種方法:
1.利用xml或者Binary序列化,然後再反序列化回來

/// <summary>
/// 使用序列化的方法實現深複製
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="destination"></param>
public static void Copy<T>(T source, ref T destination) where T : class
{
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    MemoryStream stream = new MemoryStream();
    binaryFormatter.Serialize(stream, source);
    stream.Seek(0, SeekOrigin.Begin);
    destination = (T)binaryFormatter.Deserialize(stream);
    stream.Close();
    stream.Dispose();
}

2.利用JSON序列化成JSON字符串,然後反序列化回來

public static void Copy<T>(T source, ref T destination) where T : class
  {
        string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(source);
        destination = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonStr);
  }

需要說明的是:使用ICloneable或者AutoMapper複製出來的複雜對象處理不好會是淺拷貝,還是序列化來的徹底,我推薦第二種方法,第一種類型有時候類型支持有限

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章