unity C#深拷贝、浅拷贝、直接赋值区别与经典实例

文章目录

    • 浅拷贝
    • 深拷贝
    • 浅拷贝和直接赋值有啥区别

在C#中,浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是两种不同级别的对象复制方式。它们的区别主要体现在处理引用类型字段时的行为。

浅拷贝

浅拷贝是指复制对象时,只复制对象本身所包含的值类型字段,并将引用类型字段简单地复制一份引用,而不是复制引用的对象内容。这意味着新旧对象中的引用类型字段指向相同的内存地址。因此,对任何一方引用类型的字段做出修改都会影响到另一个对象。

举例说明:

class Person
{public string Name { get; set; } // 值类型属性,字符串实际上是引用类型,但在此处作为不可变对象讨论public Car CarOwned { get; set; } // 引用类型属性
}class Car
{public string Brand { get; set; }
}// 创建原始对象
var originalPerson = new Person { Name = "Alice", CarOwned = new Car { Brand = "Toyota" } };
var shallowCopyPerson = originalPerson.MemberwiseClone(); // 使用默认的浅拷贝方法// 修改浅拷贝后的引用类型字段
shallowCopyPerson.CarOwned.Brand = "Ford";// 输出结果会显示两个对象的CarOwned.Brand都为"Frod"
Console.WriteLine(originalPerson.CarOwned.Brand); // 输出 "Ford"
Console.WriteLine(shallowCopyPerson.CarOwned.Brand); // 输出 "Ford"

在这个例子中,MemberwiseClone() 方法执行了浅拷贝操作,虽然 Person 对象被复制了一份,但 CarOwned 这个引用类型的字段并没有创建新的 Car 实例,而是共享了同一个实例。

深拷贝

深拷贝则不仅复制值类型字段,还复制引用类型字段所引用的对象,并为这些对象分配新的内存空间。这样一来,修改深拷贝后对象的引用类型字段不会影响到原对象。

深拷贝需要程序员自定义实现,通常涉及到递归遍历所有引用类型字段并逐一复制其内容。例如:

class Person
{public string Name { get; set; }public Car CarOwned { get; set; }// 自定义深拷贝方法public Person DeepCopy(){var copy = (Person)this.MemberwiseClone();if (this.CarOwned != null)copy.CarOwned = new Car { Brand = this.CarOwned.Brand }; // 深拷贝Car对象return copy;}
}class Car
{public string Brand { get; set; }
}// 创建原始对象
var originalPerson = new Person { Name = "Alice", CarOwned = new Car { Brand = "Toyota" } };
var deepCopyPerson = originalPerson.DeepCopy();// 修改深拷贝后的引用类型字段
deepCopyPerson.CarOwned.Brand = "Ford";// 输出结果会显示原对象的CarOwned.Brand仍然是"Toyota"
Console.WriteLine(originalPerson.CarOwned.Brand); // 输出 "Toyota"
Console.WriteLine(deepCopyPerson.CarOwned.Brand); // 输出 "Ford"

在上述深拷贝示例中,DeepCopy() 方法手动创建了 Car 类的新实例,这样 originalPersondeepCopyPerson 就拥有各自独立的 Car 对象,修改其中一个不会影响另一个。

浅拷贝和直接赋值有啥区别

浅拷贝(Shallow Copy)和直接赋值在处理引用类型变量时,其实是有相似之处的,但也有微妙的区别:

直接赋值:
当一个对象被直接赋值给另一个变量时,实际上创建的是原对象的一个引用副本。这意味着新变量和原变量都指向同一个内存地址,对于值类型而言,效果等同于复制了实际数据;而对于引用类型,只是复制了对原始对象的引用。

例如,在C#中:

class MyClass
{public string Value;
}MyClass obj1 = new MyClass { Value = "Hello" };
MyClass obj2 = obj1; // 直接赋值obj2.Value = "World"; // 改变 obj2 的 Value 属性

在此例中,obj2obj1 的引用副本,所以改变 obj2.Value 会导致 obj1.Value 同样变为 “World”,因为它们共享同一份引用类型的内部状态。

浅拷贝:
浅拷贝同样是创建了一个新的对象,并且复制了原对象的所有非引用类型字段值和引用类型的引用。与直接赋值类似,浅拷贝后的引用类型成员仍然指向原来的引用类型的实例。

例如,使用C#中的 MemberwiseClone() 方法进行浅拷贝:

class MyClass
{public string Value;public AnotherClass ReferenceTypeField;public MyClass ShallowCopy(){return (MyClass)this.MemberwiseClone();}
}class AnotherClass { /* ... */ }MyClass obj1 = new MyClass { Value = "Hello", ReferenceTypeField = new AnotherClass() };
MyClass obj3 = obj1.ShallowCopy(); // 浅拷贝obj3.Value = "World"; // 改变 obj3 的 Value 属性
obj3.ReferenceTypeField.SomeProperty = "New Value"; // 改变引用类型字段属性// 这里,obj1.Value 不受影响,但 obj1.ReferenceTypeField.SomeProperty 会被修改

在这个例子中,虽然 obj3obj1 的浅拷贝,改变了 obj3.Value 并不影响 obj1.Value,因为这里 Value 是值类型(字符串在.NET中是不可变类型)。然而,ReferenceTypeFieldobj1obj3 中指向的是同一个 AnotherClass 实例,因此更改 obj3.ReferenceTypeField 的属性会影响到 obj1.ReferenceTypeField

总结:

  • 直接赋值:简单地将源对象的引用传递给目标变量,两者指向相同的内存地址。
  • 浅拷贝:创建了一个新对象,其值类型字段拥有独立的副本,而引用类型字段依然指向原有对象的引用,即不创建引用类型内部状态的新副本。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SSM框架整合:掌握Spring+Spring MVC+MyBatis的完美结合!

SSM整合 1.1 流程分析1.2 整合配置步骤1:创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properties步骤8:创建SpringMVC配置类步骤9:创建Web项目入口配…

中科院国产多语言大模型-YAYI2开源!家族AI应用场景全覆盖!

项目简介 YAYI 2 是中科闻歌研发的新一代开源大语言模型,中文名:雅意,采用了超过 2 万亿 Tokens 的高质量、多语言语料进行预训练。 开源地址:https://github.com/wenge-research/YAYI2 YAYI2-30B是其模型规模,是基…

设计模式之访问者模式【行为型模式】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档> 学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某…

推荐两款好用的卫星地图。

问题描述:推荐两款好用的卫星地图。 问题解决:谷歌地球、高德卫星地图。个人感觉谷歌地球好用一些。

金蝶云星空和吉客云单据接口对接

金蝶云星空和吉客云单据接口对接 对接系统:吉客云 吉客云是基于“网店管家”十五年电商ERP行业和技术积累基础上顺应产业发展需求,重新定位、全新设计推出的换代产品,从业务数字化和组织数字化两个方向出发,以构建流程的闭环为依归…

基于卡尔曼滤波的声源跟踪方法研究

基于卡尔曼滤波的声源跟踪方法研究 摘 要一、研究意义二、研究内容三、算法介绍3.1基于到达时间差的定位算法3.1.1算法原理介绍3.1.2仿真实验设计与分析 3.2扩展卡尔曼滤波算法3.2.1算法的基本原理3.2.2仿真实验及分析 3.3无迹卡尔曼滤波算法3.3.1算法的基本原理3.3.2仿真实验及…

web学习笔记(十五)

目录 1.Date对象 1.1日期对象的概念 1.2Date()方法的使用 1.3Date()常用方法汇总 1.4例题:用函数编写一个倒计时 2.函数 2.1函数的概念 2.2函数的使用 2.3函数的参数 2.4函数的声明 2.5函数的返回值 2.6异步函数 3特殊函数类型 3.1匿名函数 3.2箭头函数…

精细微调技术在大型预训练模型优化中的应用

目录 前言1 Delta微调简介2 参数微调的有效性2.1 通用知识的激发2.2 高效的优化手段3 Delta微调的类别3.1 增量式微调3.2 指定式微调3.3 重参数化方法 4 统一不同微调方法4.1 整合多种微调方法4.2 动态调整微调策略4.3 超参数搜索和优化 结语 前言 随着大型预训练模型在自然语…

基于cy7c68013的逻辑分析仪nanoDLA全套软件linux下编译测试

0. 环境 - win10 - ubuntu22 - nanoDLA 提前获取到源码:-> 浏览器打开 https://github.com/wuxx/nanoDLA -> Download as zip. 硬件就直接用taobao买到的,原理图是 1. win10出厂测试 1.1 安装pulseview nanoDLA-master\software\pulseview-0.4.…

VGAN实现视网膜图像血管分割(基于pytorch)

背景介绍 VGAN(Retinal Vessel Segmentation in Fundoscopic Images with Generative Adversarial Networks)出自2018年的一篇论文,尝试使用生成性对抗网络实现视网膜血管分割的任务,原论文地址:https://arxiv.org/abs/1706.0931…

【K8s学习】

k8s的简单执行流程: Kubernetes Master(API Server、Scheduler等组件)负责调度Pod到合适的Node上。 当Pod被调度到某个Node时,该Node上的kubelet代理会收到指令并开始执行Pod的生命周期管理任务,包括创建、监控和终止P…

React16源码: React中的schedule调度整体流程

schedule调度的整体流程 React Fiber Scheduler 是 react16 最核心的一部分,这块在 react-reconciler 这个包中这个包的核心是 fiber reconciler,也即是 fiber 结构fiber的结构帮助我们把react整个树的应用,更新的流程,能够拆成每…