C#中的浅拷贝(Shallow Copy)和深拷贝(Deep Copy),深拷贝的集中实现方式,浅拷贝深拷贝的案例

news/2024/12/22 19:37:30/

C#中的浅拷贝(Shallow Copy)和深拷贝(Deep Copy)

拷贝就是创建一个对象,这个对象有着原始对象数据(属性和字段)的一份精确拷贝(只针对ObjectArray这样的引用数据类型)。
换个说法就是:所谓的对象拷贝(复制)就是为对象创建副本,得到相同的对象。

浅拷贝(又称为影子拷贝):(1)如果对象属性的值是值类型和string类型,拷贝的就是基本类型的值;
(2)如果对象属性是引用类型,拷贝的就是引用类型(string除外)的引用(也就是堆地址);所以修改其中一个对象引用类型数据,会影响到另一个对象;
(3)浅拷贝使用的是Object.MemberwiseClone()方法。

浅拷贝出来的副本对象中,对象里的数据(属性和字段)如果是值类型和string类型,栈中保存的就是数据自身,在原始对象和副本对象中修改值类型数据,不会相互影响(因为值类型自身在栈中有不同的内存空间);如果是引用类型,浅拷贝只是拷贝引用类型的引用(也就是堆地址),所以在原始对象和副本对象中修改引用类型数据,会相互影响(因为原始对象和副本对象拥有同一个堆地址的引用)。
在这里插入图片描述
深拷贝:(1)完全将对象中的所有数据(属性和字段)都复制到副本对象中;
(2)引用类型的数据(属性和字段)会被重新创建并且复制;所以修改其中一个对象引用类型数据,不会影响到另一个对象。

深拷贝出来的副本对象中,对象里的数据(属性和字段)如果是值类型和string类型,栈中保存的就是数据自身在原始对象和副本对象中修改值类型数据,不会相互影响(因为值类型自身在栈中有不同的内存空间);如果是引用类型,深拷贝会重新创建引用类型的数据(属性和字段)并且复制原始对象中引用类型的数据的值(堆地址中保存的具体的值),所以在原始对象和副本对象中修改引用类型数据,不会相互影响。
在这里插入图片描述

浅拷贝和深拷贝在复制原型设计模式中的对象中起着重要作用。

C#中实现深拷贝的几种方式:
1.创建一个构造函数,在构造函数中将原始对象的值一一赋值给新对象。(当对象中的变量较少的话,可以使用)

2.首先浅拷贝对象,然后重新创建对象中的引用类型的变量。

3.通过对象的序列化和反序列化功能
(1)二进制序列化和反序列化
(2)xml序列化和反序列化
(3)Json序列化和反序列化

4.通过反射和递归实现

浅拷贝和深拷贝的示例代码:

namespace ShallowAndDeepCopy
{internal class Program{//年级public class Grade{public int Stu_Grade { get; set; }}//学生public class Student{public string Name { get; set; }public int Age { get; set; }public Grade Grade { get; set; }//调用Object的MemberwiseClone方法实现浅拷贝public Student ShallowCopy(){return (Student)this.MemberwiseClone();}//实现深拷贝的一种方式//通过浅拷贝拷贝了值类型的数据//重新新建引用类型变量public Student DeepCopy(int stu_Grade){Student student = (Student)this.MemberwiseClone();student.Grade = new Grade() { Stu_Grade = stu_Grade };return student;}}private static void Main(string[] args){Console.WriteLine("-----------------下面是浅拷贝深拷贝的测试代码----------------");//创建一个原始学生对象stu1并初始化所有字段Student stu1 = new Student();stu1.Name = "张三";stu1.Age = 18;stu1.Grade = new Grade() { Stu_Grade = 8 };//声明一个学生对象,保存stu1浅拷贝的副本对象的信息Student stu2 = stu1.ShallowCopy();Console.WriteLine("浅拷贝后stu1和stu2学生信息输出:");Console.WriteLine("学生stu1的信息:");//输出学生信息OutStuMsg(stu1);Console.WriteLine("学生stu2的信息:");//输出学生信息OutStuMsg(stu2);//修改浅拷贝副本对象的信息stu2.Name = "李四";stu2.Age = 20;stu2.Grade.Stu_Grade = 9;Console.WriteLine("浅拷贝后修改stu2学生后stu1和stu2信息输出:");Console.WriteLine("学生stu1的信息:");//输出学生信息OutStuMsg(stu1);Console.WriteLine("学生stu2的信息:");//输出学生信息OutStuMsg(stu2);//声明一个学生对象,保存stu1浅拷贝的副本对象的信息Student stu3 = stu1.DeepCopy(7);Console.WriteLine("深拷贝后stu1和stu3信息输出:");Console.WriteLine("学生stu1的信息:");//输出学生信息OutStuMsg(stu1);Console.WriteLine("学生stu3的信息:");//输出学生信息OutStuMsg(stu3);//修改深拷贝副本对象的信息stu3.Name = "王麻子";stu3.Age = 25;stu3.Grade.Stu_Grade = 10;Console.WriteLine("深拷贝后修改stu3学生后stu1和stu3信息输出:");Console.WriteLine("学生stu1的信息:");//输出学生信息OutStuMsg(stu1);Console.WriteLine("学生stu3的信息:");//输出学生信息OutStuMsg(stu3);}public static void OutStuMsg(Student student){Console.WriteLine($"姓名:{student.Name}    年龄:{student.Age}");Console.WriteLine($"年级:{student.Grade.Stu_Grade} \n");}}
}

运行结果:
在这里插入图片描述
参考文章:
http://t.csdnimg.cn/qLenZ
https://docs.microsoft.com/zh-tw/dotnet/api/system.object.memberwiseclone?view=net-6.0


http://www.ppmy.cn/news/1438575.html

相关文章

【JavaEE多线程】深入解析Java并发工具类与应用实践

目录 JUC(java.util.concurrent)的常见类Callable 接口ReentrantLock原子类线程池ExecutorService 和 ExecutorsThreadPoolExecutor信号量 SemaphoreCountDownLatch 集合类多线程环境使用 ArrayList多线程环境使用队列多线程环境使用哈希表 JUC(java.util.concurrent)的常见类 …

Gateway网关跨域问题

一、模拟跨域问题 通过vscode打开,模拟跨域问题的前端资料,在黑马视频中老师那个命令我似乎是不行的,应该是还没下载相关操作指令,但是可以通过下载一个插件来实现启动(Live Server)。 下载好后右键&#…

内置对象部分

一,内置对象 二,math对象 不是构造函数,不需要new来调用,而是直接使用里面的属性和方法即可 1.随机方法random 返回一个随机的小数 [0,1) 2.日起格式化 返回的月份会小一,记得加一 周一返回1&#xff…

HarmonyOS开发实例:【图片编辑应用】

介绍 本篇Codelab通过动态设置元素样式的方式,实现几种常见的图片操作,包括裁剪、旋转、缩放和镜像。效果如图所示: 相关概念 [image组件]:图片组件,用来渲染展示图片。[div组件]:基础容器组件&#xff0…

Swift中TableView的原理

在Swift中,TableView是一种可滚动的视图控件,它以列表的形式显示数据。TableView的原理是基于MVC(Model-View-Controller)模式,它将数据展示和用户交互的逻辑分离开来。 TableView的原理可以概括为以下几个步骤&#…

2024年深圳杯东三省数学建模联赛A题B题C题D题超详细解题思路与论文解析

《2024深圳杯&东三省数学建模思路代码成品论文》↓↓↓ https://www.yuque.com/u42168770/qv6z0d/zx70edxvbv7rheu7?singleDoc# 选题建议 ok,我也是第一时间拿到了这个深圳杯的题目,下面是2024深圳杯和东三省数学建模的各题难度分析和选题建议&am…

AD--SSL卸载--单向认证和双向认证

一.SSL卸载单向认证 1.添加SSL证书 2.添加SSL卸载策略 由于是测试模拟环境,有些效果表现不出来,配置不了卸载策略 3.起虚拟服务,服务类型选择https或者ssl ,选择SSL卸载策略 实验效果:打开网页进入AD抓包发现,客户端和…

如何在PostgreSQL中创建一个新的数据库,并指定所有者?

文章目录 解决方案示例代码 PostgreSQL是一个强大的开源关系型数据库管理系统,它允许用户创建和管理多个数据库。在PostgreSQL中创建一个新的数据库并指定所有者是一个常见的操作。下面,我们将详细解释如何执行这一操作,并提供示例代码。 解…