当前位置: 首页 > news >正文

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)。

相关文章:

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

C# 深层副本与浅层副本 数据复制是编程中的重要任务。 对象是 OOP 中的复合数据类型。 对象中的成员字段可以按值或按引用存储。 可以以两种方式执行复制。 浅表副本将所有值和引用复制到新实例中。 引用所指向的数据不会被复制; 仅指针被复制。 新的引用指向原始…...

CH06_Lambda表达式

第6章:Lambda表达式 本章目标 为什么要学习C#编程语言 了解C#相关常识 C#开发工具Visual Studio安装 掌握C#程序的开发步骤 掌握C#的注释 掌握C#的常用转义符 本章内容 lambda表达式演变史 C# 匿名函数的演变历史可以追溯到 C# 语言的不同版本,…...

大模型本地部署实践:Ollama+Open-WebUI(MacOS)

目录 什么是Ollama Ollama安装 对话界面可视化?Open-WebUI! 安装Open-WebUI 什么是Ollama Ollama是一个为简化大语言模型本地部署与交互的开源框架。它提供了用户友好的接口,帮助开发者和模型爱好者在没有依赖外部API的基础上高效地运行、…...

JavaScript——DOM编程、JS的对象和JSON

一、DOM编程 DOM(Document Object Model)编程:就是使用document对象的API,完成对网页HTML文档进行动态修改,以实现网页数据,和样式动态变化效果的编程。 (一)DOM获取元素的多种方法 1.查找元素的函数 getElementById("id值…...

SIMCom芯讯通A7680C在线升级:FTP升级成功;http升级腾讯云对象储存的文件失败;http升级私有服务器的文件成功

从事嵌入式单片机的工作算是符合我个人兴趣爱好的,当面对一个新的芯片我即想把芯片尽快搞懂完成项目赚钱,也想着能够把自己遇到的坑和注意事项记录下来,即方便自己后面查阅也可以分享给大家,这是一种冲动,但是这个或许并不是原厂希望的,尽管这样有可能会牺牲一些时间也有哪天原…...

OSRM docker环境启动

命令一把梭 wget https://download.geofabrik.de/asia/china-latest.osm.pbf docker pull osrm/osrm-backend docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-extract -p /opt/car.lua /data/china-latest.osm.pbf docker run -t -v "${PWD}:/data&q…...

Vue3 动态获取 assets 文件夹图片

我真服了Vue3 这个老六了,一个简单图片src 赋值搞得那么复杂. //item.type 是我遍历类型的类型参数 <img alt"吐槽大会" :src"getAssetUrl(item.type)" /> 基于 Vue2 的Webpack 处理,还不错,可以用/ 这种绝对路径,可以接受,虽然多了个require很不爽…...

<项目代码>YOLOv8 草莓成熟识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…...

代码随想录算法训练营第五十一天|Day51 图论

岛屿数量 深搜 https://www.programmercarl.com/kamacoder/0099.%E5%B2%9B%E5%B1%BF%E7%9A%84%E6%95%B0%E9%87%8F%E6%B7%B1%E6%90%9C.html 思路 #include <stdio.h> #define MAX_SIZE 50 int grid[MAX_SIZE][MAX_SIZE]; int visited[MAX_SIZE][MAX_SIZE]; int N, M; …...

uniapp 自定义加载组件,全屏加载,局部加载 (微信小程序)

效果图 全屏加载 页面加载使用 局部加载 列表加载里面使用 使用gif html <template><view><view class"" v-if"typeFullScreen"><view class"loading" v-if"show"><view class""><i…...

STM32完全学习——系统时钟设置

一、时钟框图的解读 首先我们知道STM32在上电初始化之后使用的是内部的HSI未经过分频直接通过SW供给给系统时钟&#xff0c;由于内部HSI存在较大的误差&#xff0c;因此我们在系统完成上电初始化&#xff0c;之后需要将STM32的时钟切换到外部HSE作为系统时钟&#xff0c;那么我…...

Github 2024-11-16Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2024-11-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Go项目1Python项目1Lapce:用 Rust 编写的极快且强大的代码编辑器 创建周期:2181 天开发语言:Rust协议类型:Apache License 2.0St…...

CH03_反射

第3章&#xff1a;反射 本章目标 掌握反射的原理 熟悉反射的基本运用 本章内容 反射是什么 C# 编译运行过程 首先我们在VS点击编译的时候&#xff0c;就会将C#源代码编译成程序集 程序集以可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式实现 程序集中包含有Microsoft …...

vue2侧边导航栏路由

<template><div><!-- :default-active"$route.path" 和index对应其路径 --><el-menu:default-active"active"class"el-menu-vertical-demo"background-color"#545c64"text-color"#fff"active-text-col…...

core 不可变类型 线程安全 record

当一个类型的对象在创建时被指定状态后&#xff0c;就不会再变化的对象&#xff0c;我们称之为不可变类型。这种类型是线程安全的&#xff0c;不需要进行线程同步&#xff0c;非常适合并行计算的数据共享。它减少了更新对象会引起各种bug的风险&#xff0c;更为安全。 System.D…...

linux之调度管理(8)-SMP cpu 的 psci启动

一、psci介绍 psci是arm提供的一套电源管理接口&#xff0c;当前一共包含0.1、0.2和1.0三个版本。它可被用于以下场景&#xff1a; &#xff08;1&#xff09;cpu的idle管理 &#xff08;2&#xff09;cpu hotplug以及secondary cpu启动 &#xff08;3&#xff09;系统shutdo…...

review-消息中间件MQ

RabbitMQ RabbitMQ&#xff0c;作为当今流行的开源消息代理软件&#xff0c;以其卓越的可靠性、灵活性和易用性在微服务架构和分布式系统中扮演着至关重要的角色。它不仅能够确保消息在不同系统组件间的高效传递&#xff0c;还能通过其高级消息队列协议&#xff08;AMQP&#x…...

leetcode400第N位数字

代码 class Solution {public int findNthDigit(int n) {int base 1;//位数int weight 9;//权重while(n>(long)base*weight){//300n-base*weight;base;weight*10;}//n111 base3 weight900;n--;int res (int)Math.pow(10,base-1)n/base;int index n%base;return String…...

前端网页开发学习(HTML+CSS+JS)有这一篇就够!

目录 HTML教程 ▐ 概述 ▐ 基础语法 ▐ 文本标签 ▐ 列表标签 ▐ 表格标签 ▐ 表单标签 CSS教程 ▐ 概述 ▐ 基础语法 ▐ 选择器 ▐ 修饰文本 ▐ 修饰背景 ▐ 透明度 ▐ 伪类 ▐ 盒子模型 ▐ 浮动 ▐ 定位 JavaScript教程 ▐ 概述 ▐ 基础语法 ▐ 函数 …...

CSS遮罩:mask

CSS属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。 // 一般用位图图片做遮罩 mask: url(~/assets/images/mask.png); mask-size: 100% 100%;// 使用 SVG 图形中的形状来做遮罩 mask: url(~/assets/images/mask.svg#star);…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...