浅复制(Shallow Copy)与深复制(Deep Copy)

简介: 复制:对象的复制是生成一个与指定对象完全一样的新对象,实现的方式根据定义可以知道,新建一个类型相同的对象,然后复制原对象的每一个成员和字段。  浅复制: class Program { static void Main(string[] args) ...

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

 浅复制:

    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面向对象编程漫谈》作者:金旭亮老师

相关文章
软件测试/测试开发|测试用例设计方法——等价类划分
软件测试/测试开发|测试用例设计方法——等价类划分
|
5月前
|
JSON 人工智能 安全
Qwen Code 能力再升级
Qwen Code v0.3.0 正式发布!全面支持 Stream JSON、多语言界面切换,提升安全稳定与生态适配,助力开发者高效构建 AI 工具。欢迎体验并参与共建!
857 1
|
算法 定位技术 C++
基本算法-回溯法(迷宫问题)
基本算法-回溯法(迷宫问题)
1856 0
|
9月前
|
人工智能 安全 算法
2025 WAIC探展合合信息展台:AI鉴伪技术洞察“看不见”的伪造痕迹
2025 WAIC世界人工智能大会上,合合信息展台展示了多项AI鉴伪黑科技,涵盖图像、视频和文档篡改检测,能毫秒级识别AI伪造内容,广泛应用于金融、保险、社交媒体等多个领域,助力构建安全可信的AI生态。
335 0
2025 WAIC探展合合信息展台:AI鉴伪技术洞察“看不见”的伪造痕迹
|
SQL 存储 缓存
阿里云EMR StarRocks X Paimon创建 Streaming Lakehouse
本文介绍了阿里云EMR StarRocks在数据湖分析领域的应用,涵盖StarRocks的数据湖能力、如何构建基于Paimon的实时湖仓、StarRocks与Paimon的最新进展及未来规划。文章强调了StarRocks在极速统一、简单易用方面的优势,以及在数据湖分析加速、湖仓分层建模、冷热融合及全链路ETL等场景的应用。
780 8
阿里云EMR StarRocks X Paimon创建 Streaming Lakehouse
|
测试技术 Python
将秒换算成时、分、秒
本文介绍了使用Python将总秒数转换为小时、分钟和秒的格式的方法,包括定义转换函数和格式化输出函数,并提供了完整的代码实现及测试用例,帮助用户更友好地展示时间信息。
975 59
|
自然语言处理 前端开发 JavaScript
推荐 10 个前端开发会用到的工具网站
本文介绍了多个前端开发工具,包括 Web Design Museum、Landing Page、Google Fonts、Lorem Ipsum、Animista、Blobmaker、Spline、CodeToGo、UnusedCSS 和 Responsively,帮助开发者提高效率和项目质量。这些工具涵盖了设计、动画、代码片段管理、响应式测试等多个方面。
1029 0
推荐 10 个前端开发会用到的工具网站
|
机器学习/深度学习 数据采集 自然语言处理
利用机器学习进行文本情感分析
【10月更文挑战第4天】本文将介绍如何使用机器学习技术对文本进行情感分析,包括预处理、特征提取、模型训练和结果评估等步骤。我们将使用Python编程语言和scikit-learn库来实现一个简单的情感分析模型,并对模型的性能进行评估。
|
算法 Java
不同垃圾收集器对内存碎片的处理
不同垃圾收集器对内存碎片的处理
234 0