zoukankan      html  css  js  c++  java
  • 浅复制(Shallow Copy)与深复制(Deep Copy)

    复制:对象的复制是生成一个与指定对象完全一样的新对象,实现的方式根据定义可以知道,新建一个类型相同的对象,然后复制原对象的每一个成员和字段。

     浅复制:

    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                ClassA A = new ClassA();
                CloneObj clone = new CloneObj();
                ClassA newA= clone.CloneA(A);
            }
        }
    
        public class ClassA
        {
            public Int32 AValue = 100;
        }
    
        public class ClassB
        {
            public Int32 BValue = 200;
        }
    
        public class CloneObj
        {
            public ClassA CloneA(ClassA obj)
            {
                ClassA newAobj = new ClassA();
                newAobj.AValue = obj.AValue;
                return newAobj;
            }
        }
    复制代码

    上面的CloneObj的CloneA方法就是一个浅复制ClassA对象,修改代码:

    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                ClassA A = new ClassA();
                CloneObj clone = new CloneObj();
                ClassA newA= clone.CloneA(A);
            }
        }
    
        public class ClassA
        {
            public Int32 AValue = 100;
            public ClassB objB;
            public ClassA()
            {
                objB = new ClassB();
            }
        }
    
        public class ClassB
        {
            public Int32 BValue = 200;
        }
    
        public class CloneObj
        {
            public ClassA CloneA(ClassA obj)
            {
                ClassA newAobj = new ClassA();
                newAobj.AValue = obj.AValue;
                newAobj.objB = obj.objB;
                return newAobj;
            }
        }
    复制代码

    这里ClassA里面包含了引用类型的ClassB对象,这里复制的ClassA对象,如下图:

    上面这种方式就是“浅复制(Shallow Copy)”,这里可以在调试时测试下,看看A里面objB的地址和通过复制方法出来的newA的objB的地址:

    地址完全一样

    浅复制是.NET默认的对象复制方式,Object类提供的Memberwise方法浅复制一个对象。实现深复制,也就是上面的图中,不是共用一个ClassB对象,而是完全创建一个新的ClassB对象。这需要实现ICloneable接口.如下:

    复制代码
    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                ClassA A = new ClassA();
                CloneObj clone=new CloneObj();
                ClassA newA = clone.CloneA(A);
    
            }
        }
    
        public class ClassA:ICloneable
        {
            public Int32 AValue = 100;
            public ClassB objB;
            public ClassA()
            {
                objB = new ClassB();
            }
    
            object ICloneable.Clone()
            {
                ClassA objA = new ClassA();
                objA.AValue = this.AValue;
                objA.objB = (this.objB as ICloneable).Clone() as ClassB;
                return objA;
            }
        }
    
        public class ClassB:ICloneable
        {
            public Int32 BValue = 200;
    
            object ICloneable.Clone()
            {
                ClassB objB = new ClassB();
                objB.BValue = this.BValue;
                return objB;
            }
        }
    
        public class CloneObj
        {
            public ClassA CloneA(ClassA obj)
            {
                //ClassA newAobj = new ClassA();
                //newAobj.AValue = obj.AValue;
                //newAobj.objB = obj.objB;
                ClassA newAobj = (obj as ICloneable).Clone() as ClassA;
                return newAobj;
            }
        }
    
    }
    复制代码

    测试结果如图:

    这里完成了深复制

    对象序列化

    对象复制比较简单的方式是序列化,将类标记为[Serializable]。对象序列化主要解决的是对象状态的保存问题,这里所说的“对象状态”是指某一时刻对象拥有的字段值的集合。

    对象的序列化:将一个内存的对象保存到流中,并在需要时从流中读取数据重建对象的过程称为“对象序列化”和“反序列化”

    流:代表一连串有顺序的二进制数据。

    利用序列化进行对象的复制——深复制

    复制代码
        [Serializable]
        class MyClass
        {
            public int Index = 1;
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                MyClass obj = new MyClass();
                //创建一个内存流对象
                using (MemoryStream ms = new MemoryStream())
                {
                    IFormatter formator = new BinaryFormatter();
                    formator.Serialize(ms, obj);  //将对象序列化到内存流中 
    
                    //克隆100个对象
                    for (int i = 0; i < 100; i++)
                    {
                        ms.Seek(0, SeekOrigin.Begin);//回到流的开头
                        obj = (formator.Deserialize(ms) as MyClass); //反序列化对象
                        obj.Index += i;   //设置对象字段
                        Console.WriteLine("对象{0}已创建。", obj.Index);
                    }
                }
                Console.ReadKey();
            }
        }
    复制代码

    原理是将对象序列化到流中,然后从流中创建对象(批量),从而实现了深复制。

    以上内容整理自《.NET4.0面向对象编程漫谈》作者:金旭亮老师

    作者:Gabriel Zhang
    出处:http://www.cnblogs.com/mszhangxuefei/
    本文版权归作者和博客园共有,欢迎转载,但必须注明出处,并在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    我只有一件事,就是忘记背后,努力面前的,向着标竿直跑

     
    分类: C#.NET点滴
  • 相关阅读:
    Android学习笔记之-Websercive 通讯
    Android学习笔记
    Android学习笔记-Android生成数字证书+签名
    jQuery教程总结
    SQL 数据库备份和恢复 镜像配置(证书方式)
    【网络部分总结的很好的帖子】方便以后找
    【动态规划】最长递增子序列
    【美团~牛客】十六进制转十进制
    【二分查找】及相关问题
    【动态规划】
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2875759.html
Copyright © 2011-2022 走看看