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复制出来的复杂对象处理不好会是浅拷贝,还是序列化来的彻底,我推荐第二种方法,第一种类型有时候类型支持有限

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