C#深度复制和浅度复制

复制一个值变量很简单,新建一个变量然后将原来的变量赋值过去就行,但是复制一个引用变量这种方法是不行的,如果不明白为什么可以先看看这篇解释

引用类型变量和值类型变量在赋值时的不同

如果要复制一个引用类型的变量,比如说类,需要在类定义中继承ICloneable接口,并实现Clone方法,这是一个固定格式,下面看一个例子

 public class Test:ICloneable
{
public int Val;
public object Clone() => MemberwiseClone();
}

定义了一个Test类,继承ICloneable接口,实现Clone方法,实现Clone方法的格式是固定的,这里使用了简化写法,public object Clone() => MemberwiseClone();等于

public object Clone()
{
return MemberwiseClone();
}

这是C#提供的方法,按照这么写就对了,此时如果要复制一个Test类的引用变量,就可以这么写

Test t1 = new Test();
Test t2 = (Test)t1.Clone();

有一个引用类型变量t1,调用t1.Clone()会在堆中重新开辟一个内存空间,并且复制t1堆空间的值,然后会返回这个新空间的内存地址,因为Clone()方法返回类型是object,所以强制类型转换为Test,然后赋给Test类型的变量t2

这个过程,便是C#中的浅度复制(ShallowCopy),也有称为影子复制的

这个复制会存在一些问题,那就是一个引用类型中存在引用类型字段时,引用类型字段并不会也复制一份

public class Test:ICloneable
{
public int Val;
public Test2 Z = new Test2();
public object Clone()
{
return MemberwiseClone();
}
}
public class Test2
{
public int D;
}

这里定义了两个类,其中Test类中包含了一个Test2类型的引用类型变量Z,我们先看内存中怎样表示的

从这张图我们可以看到,当我们使用Clone对引用类型进行Clone时,只会复制堆空间的值,如果堆空间中有引用类型,在复制时就只单纯的复制了引用类型的堆空间地址,这样的后果就是虽然Clone得到了两个堆空间对象,但是堆空间对象中的字段却指向了同一个另外的空间地址,在某些情况下就会出现问题

所以

浅度复制:解决了直接使用赋值运算符时变量指向了同一个堆空间的问题(即Test t2 = t1的问题),但是只解决了一层,对于包含在内的堆空间中的成员的引用没有进一步解决(即t1.Z和t2.Z指向了同一个堆空间地址)

为了解决上述问题,就需要使用深度复制,深度复制的基本思路,就是在Clone方法中创建一个新的对象并使其内容与现有内容保持一致(其实是废话),我们甚至可以不用继承ICloneable,但是建议继承并使用Clone方法,这样可以保持方法名的一致性

至于怎么实现,可以自行思考(主要是我也在思考中)

所以这篇文章的主要内容是讲:C#提供的return MemberwiseClone();只是浅度复制,不会为引用成员创建新空间并将引用成员空间的值复制过去,只会复制引用成员的空间地址,需要注意

C#深度复制和浅度复制的更多相关文章

  1. .NET基础之深度复制和浅度复制

    之前一直没有搞清楚深度复制和浅度复制的区别到底在哪里,今天彻底把这个东西弄懂了,写出来与到家共勉. 如果大家不懂值类型和引用类型的区别,请先看http://www.cnblogs.com/Autumo ...

  2. c#学习笔记-深度复制 与浅度复制

    关于值类型和引用类型: 浅度复制(shallow copy)只复制值类型(char,int )的值,而对于引用类型不会复制,浅度复制可以通过派生于System.Object的MemberwiseClo ...

  3. 转载---Java集合对象的深度复制与普通复制

    原博文:http://blog.csdn.net/qq_29329775/article/details/49516247 最近在做算法作业时出现了错误,原因是没有弄清楚java集合的深度复制和浅度复 ...

  4. [No0000B9]C# 类型基础 值类型和引用类型 及其 对象复制 浅度复制vs深度复制 深入研究2

    接上[No0000B5]C# 类型基础 值类型和引用类型 及其 对象判等 深入研究1 对象复制 有的时候,创建一个对象可能会非常耗时,比如对象需要从远程数据库中获取数据来填充,又或者创建对象需要读取硬 ...

  5. 深度解析javascript中的浅复制和深复制

    原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null ...

  6. Java的深度克隆和浅度克隆

    说到克隆,其实是个比较简单的概念,跟现实生活正的克隆一样,复制一个一模一样的对象出来.clone()这个方法是从Object继承下来的,一个对象要实现克隆,需要实现一个叫做Cloneable的接口,这 ...

  7. List的深度copy和浅度拷贝

    List<Student> list= Arrays.asList( new Student("Fndroid", 22, Student.Sax.MALE, 180) ...

  8. Cloneable接口的作用与深度克隆与浅度克隆

    cloneable接口的作用 cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现这个接口,则 ...

  9. js中的深复制和浅复制

    在实际情况中经常会遇到对对象复制的问题.比如在处理项目中的一笔多结构的数据存储或者调用,这个时候你就要对对象(json)进行操作,而不同的操作根据不同的需求来定义.其中最常见最普遍的是对对象的复制,重 ...

随机推荐

  1. Ubuntu上安装Python3编译器和 Pycharm 集成开发环境

    一.安装python3 (Ubuntu上面是自带python编译器的,可以用命令"python -V"来查看版本号.我下面安装的是pyhton3编译器) 一条命令就可以 sudo ...

  2. CF1466-C. Canine poetry

    CF1466-C. Canine poetry 题意: 给出一个字符串,这个字符串里面可能会包含多个回文子字符串.现在你可以任意修改这个字符串中的任意一个字符任意次数,问你最少多少操作数之后这个字符串 ...

  3. [Golang]-7 定时器和打点器

    目录 定时器 打点器 After()方法 我们常常需要在未来某个时刻运行 Go 代码,或者在某段时间间隔内重复运行. Go 的内置 定时器 和 打点器 特性让这些很容易实现. 定时器 type Tim ...

  4. 在kubernetes集群里集成Apollo配置中心(6)之实战使用apollo分环境管理dubbo服务

    生产实践 1.迭代新需求/修复BUG(编码--->提git) 2.测试环境发版,测试(应用通过编译打包发布至test命名空间) 3.测试通过,上线(应用镜像直接发布至prod命名空间) 系统架构 ...

  5. Kubernets二进制安装(14)之flannel之SNAT规则优化

    flannel之SNAT规则优化的目的是由于在K8S中的容器内,访问不同宿主机中的容器的资源的时候,日志文件会记录为宿主机的IP地址,而不是记录为容器本身自己的IP地址,建议在不同的宿主机上的容器互访 ...

  6. codeforces 1028C Rectangles【思维】

    题目:戳这里 题意:有n个矩阵,求一个点(保证存在)至少在n-1个点内. 解题思路:因为矩阵与坐标轴平行,所以我们画图可以发现如果存在点满足条件,则这些点中一定有一个是矩阵的顶点.我们可以把所有顶点的 ...

  7. chrome禁用缓存:调试javascript注意事项

    chrome禁用缓存:调试javascript   chrome对js和图片的缓存,导致调试的程序不是最新的,有时F5刷新了都没用. 可以禁用缓存: 先按F12,再按F1, 勾选 Disable ca ...

  8. ES6 Map to Array

    ES6 Map to Array function differentSymbolsNaive(str) { // write code here. const map = new Map(); co ...

  9. JavaScript var, let, const difference All In One

    JavaScript var, let, const difference All In One js var, let, const 区别 All In One 是否存在 hoisting var ...

  10. js replace all

    js replace all https://stackoverflow.com/questions/1144783/how-can-i-replace-all-occurrences-of-a-st ...