【Basic Code】深拷贝、浅拷贝的代码实现(一)

来源:互联网 发布:分卷包数据不正确修复 编辑:程序博客网 时间:2024/06/04 23:23

一、是什么?

      在代码中为对象创建副本的技术叫做复制(拷贝),复制分类为浅复制和深复制,前者修改副本中的值类型数据不会修改原对象,但是修改副本中的引用类型数据会修改原对象;后者无论修改副本中的值类型还是引用类型都不会对原对象改动。

 

二、应用场景

       在工作中用到了深复制的代码实现,主要基于不想改变原有数据的完整性,通过DeepClone来解决;同时对于浅复制,我个人认为MVVM中Binding机制里的双向绑定就是这个原理。

      暂时理解到这里,欢迎网友们交流在项目中深浅复制的应用以及源码分享交流。

 

三、怎么玩?

       世界上所有的问题没有一个Demo(一顿麻辣烫)解决不了的,解决不了就再来一个(再来一顿)。

由于我工作是敲C#代码,对于Microsoft这个大体系,是通过继承ICloneable接口来实现的,当然这个接口中只有一个Clone方法,实现深、浅复制是还需要我们自己动手的,看代码吧:

   1、浅复制:

    (1)继承IClone接口,并实现其Clone方法:    

class Employee : ICloneable    {        public string IDCode { get; set; }        public string WorkExperience { get; set; }        public int Age { get; set; }        public Department Department { get; set; }        #region IClone 成员        //浅复制的Clone方法实现        public object Clone()        {            return this.MemberwiseClone();        }        #endregion    }
    (2)引用类型Department的类

class Department    {        public string Name { get; set; }        public override string ToString()        {            return this.Name;        }    }
     (3)控制台应用程序的Main方法调用

static void Main(string[] args)        {            Employee Vincent = new Employee()            {                IDCode = "11",                Age = 24,                WorkExperience = "0",                Department = new Department() { Name = "TGB" }            };            //浅复制            Employee Tom = Vincent.Clone() as Employee;            Console.WriteLine("Vincent几个月前的身份:");            Console.WriteLine("ID号码:" + Tom.IDCode);            Console.WriteLine("年龄:" + Tom.Age);            Console.WriteLine("工作单位:" + Tom.Department);            //换行            Console.WriteLine("");            Console.WriteLine("出去实习,开始改变Vincent的身份");            Vincent.IDCode = "102";            Vincent.WorkExperience = "3";            Vincent.Age = 26;            Vincent.Department.Name = "乐客VR";            Console.WriteLine("ID号码:" + Tom.IDCode);            Console.WriteLine("年龄:" + Tom.Age);            Console.WriteLine("工作单位:" + Tom.Department);            Console.ReadKey();        }
       那我自己这个月身份的变化,写了一个小Demo,注意浅复制核心语句是实现ICloneable的Clone方法,程序输出如下:

       

        仔细观察代码,在我将“Employee Tom = Vincent.Clone() as Employee;”之后,第一次输出Tom的信息,和Vincent的一模一样,当我再次改变Vincent的个人信息之后,再次Console 一下Tom的信息发现,工作单位从"TGB"变化成了“乐客VR”,而这个Department对象,恰恰对于Main方法所在的类是个引用,则说明,浅复制在改变值类型后,对备份无影响,但是改变了引用类型,则备份也发生改变,备份不够彻底,就是“浅复制”,姑且这样理解。


   2、深复制

      继续上面这个例子,修改IClone接口的实现方法,同时将Employee标识为可序列化

#region IClone 成员        //浅复制的Clone方法实现        public object Clone()        {            using(Stream objectStream = new MemoryStream())            {                //先将对象格式化                IFormatter formatter = new BinaryFormatter();                //将其序列化                formatter.Serialize(objectStream, this);                //派生类重写时,设置起始位置                objectStream.Seek(0, SeekOrigin.Begin);                //反序列化,并形成对象                return formatter.Deserialize(objectStream) as Employee;            }        }        #endregion
     如图:

               

       此时,就实现了完全复制,即使之后代码修改了引用类型的属性,也不会改变我备份后的结果。


四、总结

      上面的方法实现深复制和浅复制,是通过实现Microsoft里的IClone接口,当然这个接口使我们自己来实现的,以上是用过序列化和反序列化实现深复制,是一种不错的方式,下一篇博客,就实战我项目中的一个深复制实现。


1 0