C# 深层副本与浅层副本 深拷贝与浅拷贝

C# 深层副本与浅层副本

数据复制是编程中的重要任务。 对象是 OOP 中的复合数据类型。 对象中的成员字段可以按值或按引用存储。 可以以两种方式执行复制。

浅表副本将所有值和引用复制到新实例中。 引用所指向的数据不会被复制; 仅指针被复制。 新的引用指向原始对象。 对引用成员的任何更改都会影响两个对象。

深层副本将所有值复制到新实例中。 如果成员存储为引用,则深层副本将对正在引用的数据执行深层副本。 创建一个引用对象的新副本。 并存储指向新创建对象的指针。 对这些引用对象的任何更改都不会影响该对象的其他副本。 深拷贝是完全复制的对象。

如果成员字段是值类型,则将对该字段进行逐位复制。 如果该字段是引用类型,则复制引用,但不是复制引用的对象。 因此,原始对象中的引用和克隆对象中的引用指向同一对象。 (来自 programmingcorner.blogspot.com 的明确解释)

C# 浅表复制

以下程序执行浅表复制。

Program.
using System;namespace ShallowCopy
{class Color{public int red;public int green;public int blue;public Color(int red, int green, int blue){this.red = red;this.green = green;this.blue = blue;}}class MyObject : ICloneable{public int id;public string size;public Color col;public MyObject(int id, string size, Color col){this.id = id;this.size = size;this.col = col;}public object Clone(){return new MyObject(this.id, this.size, this.col);}public override string ToString(){var s = String.Format("id: {0}, size: {1}, color:({2}, {3}, {4})",this.id, this.size, this.col.red, this.col.green, this.col.blue);return s;}}class Program{static void Main(string[] args){var col = new Color(23, 42, 223);var obj1 = new MyObject(23, "small", col);var obj2 = (MyObject) obj1.Clone();obj2.id += 1;obj2.size = "big";obj2.col.red = 255;Console.WriteLine(obj1);Console.WriteLine(obj2);}}
}

这是一个浅表副本的示例。 我们定义了两个自定义对象:MyObjectColor。 MyObject对象将引用 Color 对象。

class MyObject : ICloneable

我们应该为要克隆的对象实现ICloneable接口。

public object Clone()
{return new MyObject(this.id, this.size, this.col);
}

ICloneable接口迫使我们创建Clone()方法。 此方法返回具有复制值的新对象。

var col = new Color(23, 42, 223);  

我们创建 Color 对象的实例。

var obj1 = new MyObject(23, "small", col);

创建MyObject类的实例。 Color对象的实例传递给构造函数。

var obj2 = (MyObject) obj1.Clone();

我们创建 obj1 对象的浅表副本,并将其分配给 obj2 变量。 Clone()方法返回Object,我们期望MyObject。 这就是我们进行显式转换的原因。

obj2.id += 1;
obj2.size = "big";         
obj2.col.red = 255;

在这里,我们修改复制对象的成员字段。 我们增加 id,将大小更改为“大”,然后更改颜色对象的红色部分。

Console.WriteLine(obj1);
Console.WriteLine(obj2);

Console.WriteLine()方法调用obj2对象的ToString()方法,该方法返回对象的字符串表示形式。

$ dotnet run
id: 23, size: small, color:(255, 42, 223)
id: 24, size: big, color:(255, 42, 223)

我们可以看到 ID 是不同的(23 对 24)。 大小不同(“小”与“大”)。 但是,这两个实例的颜色对象的红色部分相同(255)。 更改克隆对象的成员值(id,大小)不会影响原始对象。 更改引用对象(col)的成员也影响了原始对象。 换句话说,两个对象都引用内存中的同一颜色对象。

C# 深层复制

要更改此行为,我们接下来将做一个深层复制。

Program.
using System;namespace DeepCopy
{class Color : ICloneable{public int red;public int green;public int blue;public Color(int red, int green, int blue){this.red = red;this.green = green;this.blue = blue;}public object Clone(){return new Color(this.red, this.green, this.blue);}}class MyObject : ICloneable{public int id;public string size;public Color col;public MyObject(int id, string size, Color col){this.id = id;this.size = size;this.col = col;}public object Clone(){return new MyObject(this.id, this.size,(Color)this.col.Clone());}public override string ToString(){var s = String.Format("id: {0}, size: {1}, color:({2}, {3}, {4})",this.id, this.size, this.col.red, this.col.green, this.col.blue);return s;}}class Program{static void Main(string[] args){var col = new Color(23, 42, 223);var obj1 = new MyObject(23, "small", col);var obj2 = (MyObject) obj1.Clone();obj2.id += 1;obj2.size = "big";obj2.col.red = 255;Console.WriteLine(obj1);Console.WriteLine(obj2);}}
}

在此程序中,我们对对象执行深层复制。

class Color : ICloneable

现在,Color 类实现了ICloneable接口。

public object Clone()
{return new Color(this.red, this.green, this.blue);
}

我们也为Color类提供了Clone()方法。 这有助于创建引用对象的副本。

public object Clone()
{return new MyObject(this.id, this.size, (Color) this.col.Clone());
}

当我们克隆MyObject时,我们根据 col 引用类型调用Clone()方法。 这样,我们也可以获得颜色值的副本。

$ dotnet run
id: 23, size: small, color:(23, 42, 223)
id: 24, size: big, color:(255, 42, 223)

现在,所引用的 Color 对象的红色部分不再相同。 原始对象保留了其先前的值(23)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19170.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

sglang 部署Qwen2VL7B,大模型部署,速度测试,深度学习

sglang 项目github仓库: https://github.com/sgl-project/sglang 项目说明书: https://sgl-project.github.io/start/install.html 资讯: https://github.com/sgl-project/sgl-learning-materials?tabreadme-ov-file#the-first-sglang…

『大模型笔记』AI自动化编程工具汇总!

『大模型笔记』AI自动化编程工具汇总! 文章目录 一. Bolt.new(开源AI驱动全栈Web开发工具)1.1. Bolt.new介绍1.2. 编程小白如何打造自己的导航网站二. Cursor(人工智能代码编辑器)2.1. Cursor入门教程2.2. Cursor左侧布局设置和VSCode一样一. Bolt.new(开源AI驱动全栈Web开发工…

网页全终端安防视频流媒体播放器EasyPlayer.jsEasyPlayer.js关于多屏需求

EasyPlayer.js网页全终端安防视频流媒体播放器是一款功能强大的H5播放器,支持多种视频协议,包括HTTP、HTTP-FLV、HLS(m3u8)、WS、WEBRTC、FMP4等,兼容视频直播与点播功能。同时,它支持多种音视频编码格式&a…

大模型外挂知识库优化——如何利用大模型辅助召回

大模型外挂知识库优化——如何利用大模型辅助召回? 一、为什么需要使用大模型辅助召回? 我们可以通过向量召回的方式从文档库里召回和用户问题相关的文档片段,同时输入到LLM中,增强模型回答质量。 常用的方式直接用用户的问题进…

three.js实现地球 外部扫描的着色器

three.js实现地球 外部扫描的着色器 https://threehub.cn/#/codeMirror?navigationThreeJS&classifyshader&idearthScan import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js import { GUI } from three/ex…

STM32 BootLoader 刷新项目 (十一) Flash写操作-命令0x57

STM32 BootLoader 刷新项目 (十一) Flash写操作-命令0x57 1. 引言 嵌入式系统中,BootLoader 是设备启动的第一部分代码,负责硬件初始化和主程序加载。在 STM32F407 中,BootLoader 的另一重要功能是支持应用程序的在线升级,这需要…

Spring IoC——针对实习面试

目录 Spring IoC谈谈你对Spring IoC的理解IoC和DI有区别吗?IoC(控制反转)DI(依赖注入)IoC与DI的区别 什么是Spring Bean?作用域有哪些?Bean是线程安全的吗?说一下Spring Bean的生命周…

【H2O2|全栈】MySQL的云端部署

目录 前言 开篇语 准备工作 MySQL移除 为什么需要移除? 移除操作 Yum仓库 yum简介 rpm安装 yum库安装 MySQL安装 使用yum安装 开机自启动 检查运行状态 MySQL配置 初始密码 ​编辑登录 修改root密码 退出MySQL 字符集配置 结束语 前言 开篇语…

数据结构-二叉平衡树

一.平衡二叉树 二叉搜索树插入的次序不同导致不同的深度和平均查找长度ASL 左右子树高度差不超过绝对值1的二叉搜索是二叉平衡树 二.平衡二叉树的调整 在右子树的右子树上的插入做RR插入 把被破坏节点的右子树变成跟节点并把这个右子树的左子树挂载到原来被破坏的结点的右子树…

【PCIE716-0】基于PCIe总线架构的XC7Z100 FPGA高性能实时信号处理平台

板卡概述 PCIE716-0是一款基于PCIe总线架构的XC7Z100 FPGA高性能实时信号处理平台。该平台采用Xilinx的ZYNQ SOC系列产品XC7Z100作为主处理器。 该平台的PL端具有1个FMC(HPC)接口,1路PCIe x8主机接口,支持1路UART串口、支持1组6…

从0开始的数据结构速过——番外(1)

目录 尝试 思考与架构设置 编写! 一些额外知识的补充 可变参数模板 std::common_type std::forward 这是《数据结构从0开始》的一个番外。实际上是介绍一下一些现代C的写法。这里以快速构建std::array作为契机来说明一下一些现代C的语法。 尝试 我们在这里呢…

Day10_CSS过度动画

Day10_CSS过度动画 背景 : PC和APP项目我们已经开发完毕, 但是再真正开发的时候有些有些简易的动态效果我们可以使用CSS完成 ; 本节课我们来使用CSS完成基础的动画效果 今日学习目标 CSS3过度CSS3平面动态效果CSS3动画效果案例 1. CSS3过渡 ​ 含义 :过渡指的是元素从一种…

如何制作代购系统的客服支持模块

在代购系统中,客服支持模块是维护用户满意度和忠诚度的关键环节。一个有效的客服支持模块不仅可以解决用户的疑问和问题,还可以收集用户反馈,用于改进服务和产品。本文将详细介绍如何制作一个代购系统的客服支持模块,包括前端界面…

【unity小技巧】一些unity3D灯光的使用与渲染及性能优化方案

文章目录 天空盒反射配置太阳耀斑眩光烘培光照烘培光照时弹出错误,记得勾选模型下面的选择阴影项目配置光源模型模型shader的问题 全局光照混合光照模式混合照明模式减性照明模式Shadowmask照明模式间接烘焙照明模式 环境光遮罩灯光探针反射探针技术关闭反射探针可以…

Spring Boot汽车资讯:科技与汽车的对话

5系统详细实现 5.1 管理员模块的实现 5.1.1 用户信息管理 汽车资讯网站的系统管理员可以管理用户,可以对用户信息修改删除审核以及查询操作。具体界面的展示如图5.1所示。 图5.1 用户信息管理界面 5.1.2 汽车品牌管理 系统管理员可以汽车品牌信息进行添加&#xf…

go 学习网站,go例子 go demo go学习视频

1. 代码例子: Go by Example 2. b站 视频: 尚硅谷视频: 004_尚硅谷_程序的基本概念_哔哩哔哩_bilibili 3. go技术文档: fmt Go语言中文文档

记录下,用油猴Tampermonkey监听所有请求,绕过seesion

油猴Tampermonkey监听所有请求,绕过seesion 前因后果脚本编写 前因后果 原因是要白嫖一个网站的接口,这个接口的页面入口被隐藏掉了,不能通过页面调用,幸好之前有想过逆向破解通过账号密码模拟登录后拿到token,请求该…

网络安全:我们的安全防线

在数字化时代,网络安全已成为国家安全、经济发展和社会稳定的重要组成部分。网络安全不仅仅是技术问题,更是一个涉及政治、经济、文化、社会等多个层面的综合性问题。从宏观到微观,网络安全的重要性不言而喻。 宏观层面:国家安全与…

多账号登录管理器(淘宝、京东、拼多多等)

目录 下载安装与运行 解决什么问题 功能说明 目前支持的平台 功能演示 登录后能保持多久 下载安装与运行 下载、安装与运行 语雀 解决什么问题 多个账号的快捷登录与切换 功能说明 支持多个电商平台支持多个账号的登录保持支持快捷切换支持导入导出支持批量删除支持…

浅谈网络 | 二层到三层

目录 物理层到MAC层第一层(物理层)第二层(数据链路层)局域网 交换机与VLAN生成树协议VLAN ICMP与pingICMP 协议的格式 网关静态路由是什么? 路由协议如何配置策略路由?动态路由算法动态路由协议 物理层到MA…