技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

1、关于深拷贝和浅拷贝

C#支持两种类型:值类型和引用类型

值类型(Value Type):如 char, int, float,枚举类型和结构类型

引用类型(Reference Type):如Class类型、接口类型、委托类型、数组类型。

如何来划分它们?

以它们在计算机内存中如何分配来划分。

堆栈(Stack)是一种先进先出的数据结构,在内存中,变量会被分配在堆栈上来进行操作。

堆(Heap)是用于为类型实例(对象)分配空间的内存区域,在堆上创建一个对象,会将对象的地址传递给堆栈上的变量(反过来叫变量指向此对象,或者变量引用此对象)。

值类型与引用类型的区别?

(1)、值类型的变量直接包含其数据

(2)、引用类型的变量则存储对象引用

对于引用类型,两个变量可能引用同一个对象,因此对一个变量的操作可能影响到另一个变量所引用的对象。

对于值类型,每个变量都有自己的数据副本,对于一个变量的操作不可能影响到另一个变量。

值类型隐式继承自System.ValueType,所以不能显示让一个结构继承一个类,C#不支持多继承。 

关于对象克隆的所设计到知识点

浅拷贝:是指将对象中的所有字段逐字复制到一个新对象

对值类型字段只是简单的拷贝一个副本到目标对象,改变目标对象中值类型字段的值不会反映到原始对象中,因为拷贝的是副本。实现浅拷贝需要使用Object类的MemberwiseClose方法用于创建一个浅表副本。

对引用类型字段则是指拷贝他的一个引用到目标对象,改变目标对象中引用类型字段的值会将它反映到原始对象中,因为拷贝的是指向堆是上的一个地址。

深拷贝:深拷贝与浅拷贝不同的是对于引用字段的处理,深拷贝会将在新对象中创建一个新的对象和原始对象字段相同(内容相同)的字段,也就是说这个引用和原始对象引用是不同,我们改变新对象这中这个字段的时候是不会影响到原始对象中对应字段的内容。须实现ICloneable接口中的Clone方法,且需要将被克隆对象加上[Serializable]特性。

引用类型的赋值、浅拷贝和深拷贝的区别

赋值:就是将原来对象的地址给新的对象拷贝一下即可。

浅拷贝:需要继承ICloneable接口(支持克隆,即用现有实例相同的值创建类的新实例),然后用MemberwiseClone方法(创建当前System.Object的浅表对象)。但是需要注意的是MemberwiseClone拷贝方式,首先它是浅拷贝,方法是将所有的值类型字段拷贝一个副本,但是引用类型不会创建副本,仅仅是传递一个相同的地址给新对象,并且新对象和原对象指向的地址是一致的,这里有个问题就是string类型,但是实际上却是和值类型表现一致。

深拷贝:深拷贝与浅拷贝不同的是对于引用字段的处理,深拷贝会将在新对象中创建一个新的对象和原始对象字段相同(内容相同)的字段,也就是说这个引用和原始对象引用是不同,我们改变新对象这中这个字段的时候是不会影响到原始对象中对应字段的内容。须实现ICloneable接口中的Clone方法,且需要将被克隆对象加上[Serializable]特性。

2 List 的深拷贝

代码如下:

    /// <summary>/// Class Program/// </summary>class Program{/// <summary>/// Defines the entry point of the application./// </summary>/// <param name="args">The args.</param>static void Main(string[] args){List<Person> originalList = new List<Person>();Person person = new Person();person.Name = "zhangsan";person.Age = 90;Job job = new Job();job.JobName = "开发工程师";person.PersonJob = job;originalList.Add(person);person = new Person();person.Name = "lisi2";job = new Job();job.JobName = "开发工程师";person.PersonJob = job;originalList.Add(person);person = new Person();person.Name = "3";job = new Job();job.JobName = "测试工程师";person.PersonJob = job;originalList.Add(person);Console.WriteLine("原数据如下:");for (int i = 0; i < originalList.Count; i++){Console.WriteLine("Name:" + originalList[i].Name + ",JobName:" + originalList[i].PersonJob.JobName);}Console.WriteLine("--------------List深复制------------------");List<Person> deepCopyList = Clone<Person>(originalList);deepCopyList[1].Name = "lisi";for (int i = 0; i < originalList.Count; i++){Console.WriteLine("原数据:Name:" + originalList[i].Name + ",JobName:" + originalList[i].PersonJob.JobName);Console.WriteLine("深复制后:Name:" + deepCopyList[i].Name + ",JobName:" + deepCopyList[i].PersonJob.JobName);}Console.WriteLine("----------------List赋值----------------");List<Person> shallowCopyList = originalList;shallowCopyList[2].Name = "amy";shallowCopyList[2].PersonJob.JobName = "产品工程师";Job modifyJob = new Job();modifyJob.JobName = "UNKNOWN";shallowCopyList[1].PersonJob = modifyJob;for (int i = 0; i < originalList.Count; i++){Console.WriteLine("原数据:Name:" + originalList[i].Name + ",JobName:" + originalList[i].PersonJob.JobName);Console.WriteLine("浅复制:Name:" + shallowCopyList[i].Name + ",JobName:" + shallowCopyList[i].PersonJob.JobName);}Console.Read();}/// <summary>/// Clones the specified list./// </summary>/// <typeparam name="T"></typeparam>/// <param name="List">The list.</param>/// <returns>List{``0}.</returns>public static List<T> Clone<T>(object List){using (Stream objectStream = new MemoryStream()){IFormatter formatter = new BinaryFormatter();formatter.Serialize(objectStream, List);objectStream.Seek(0, SeekOrigin.Begin);return formatter.Deserialize(objectStream) as List<T>;}}}

两个测试类代码如下:

/// <summary>/// Class Person/// </summary>[Serializable]public class Person {/// <summary>/// Gets or sets the person job./// </summary>/// <value>The person job.</value>public Job PersonJob{get;set;}/// <summary>/// Gets or sets the name./// </summary>/// <value>The name.</value>public string Name{get;set;}/// <summary>/// Gets or sets the age./// </summary>/// <value>The age.</value>public int Age{get;set;}/// <summary>/// Clones this instance./// </summary>/// <returns>System.Object.</returns>public object Clone(){BinaryFormatter formatter = new BinaryFormatter(null, new System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.StreamingContextStates.Clone));MemoryStream stream = new MemoryStream();formatter.Serialize(stream, this);stream.Position = 0;object clonedObj = formatter.Deserialize(stream);stream.Close();return clonedObj;}}/// <summary>/// Class Job/// </summary>[Serializable]public class Job{/// <summary>/// Gets or sets the name of the job./// </summary>/// <value>The name of the job.</value>public string JobName{get;set;}}

结果如下:

3 不用加Serializable的深复制方法

        public static T DeepCopy<T>(T obj){object retval;using (MemoryStream ms = new MemoryStream()){XmlSerializer xml = new XmlSerializer(typeof(T));xml.Serialize(ms, obj);ms.Seek(0, SeekOrigin.Begin);retval = xml.Deserialize(ms);ms.Close();}return (T)retval;}

C#.Net工作笔记007---关于Lst深层复制_浅层复制_提供一个方法可以直接使用相关推荐

  1. java对象复制_Java对象的深层复制与浅层复制

    TestVO a = new TestVO(); a.setName("xiemingmei"); a.setBirthPlace("Hunan"); Test ...

  2. 如何在JavaScript中区分深层副本和浅层副本

    by Lukas Gisder-Dubé 卢卡斯·吉斯杜比(LukasGisder-Dubé) 如何在JavaScript中区分深层副本和浅层副本 (How to differentiate betw ...

  3. JAVA浅层复制深层复制理解-java_01_20160824

    在java中,默认是浅层复制的,如果要复制的对象中只含有基本数据类型和String类型, 那么浅层复制和浅层复制是没有区别的,所以你可以放心的使用默认的浅层复制, 但是如果要复制的对象中除了上述类型还 ...

  4. [转载] 深层复制构造函数和浅层复制构造函数区别

    参考链接: Python复制(深层复制和浅层复制) 构造函数用来初始化对象的,复制构造函数是把一个已知的对象复制给新的对象,(2者都是对象). 浅复制构造函数只复制指针(换句话说就是2个对象的地址一样 ...

  5. 浅层学习与深层学习_深层副本与浅层副本-以及如何在Swift中使用它们

    浅层学习与深层学习 by Payal Gupta 通过Payal Gupta 深层副本与浅层副本-以及如何在Swift中使用它们 (Deep copy vs. shallow copy - and h ...

  6. python中复制、浅层拷贝、深层拷贝的区别

    python中复制.浅层拷贝.深层拷贝的区别 一.学习要点: 1.python中的复制与拷贝的区别 2.python中浅层拷贝与深层拷贝的区别 二.代码: import copy a=[1,2,3,4 ...

  7. STM32工作笔记0031---基于STM32F103C8自己实现的跑马灯实验_使用STLINK调试

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 网上买的8块一个开发版,简单的STM32F103C8,64kbflash,中容量版,这个容量 好像 ...

  8. js的深层克隆和浅层克隆代码和理解

    <script> //判断是不是原始值 //判断是数组还是对象 //建立相应的数组或对象 var obj={name:'辣鸡',sex:'male',card:['laobi','feiw ...

  9. uniapp打包安装后提示_本应用使用HBuilderX 2.8.12 或对应的cli版本编译,而手机端SDK版本是2.8.13---基于Vue的uniapp手机端_前端UI_uview工作笔记007

    解决办法: 可以在manifest.json文件的源码视图中配置忽略这个提醒,方式如下: HBuilderX1.9.0及以上版本新增以下配置避免弹出提示框 添加上面的配置就可以了 "comp ...

最新文章

  1. 解决:VS 2005/2008 中 fstream 不能处理带有中文路径的问题
  2. 数据蒋堂 | 人工智能中的“人工”
  3. 安装软件the error code is 2203解决方法
  4. 支持多编程语言的自动测试系统
  5. boost::detail模块fwd容器的测试程序
  6. CentOS6.7安装jdk1.8
  7. Android—多版本主要适配内容
  8. 分布式服务架构下的混沌工程实践
  9. netty : io.netty.handler.codec.TooLongFrameException
  10. 【图像直线拟合】基于matlab最小二乘法图像直线拟合【含Matlab源码 100期】
  11. Java 理论与实践: 您的小数点到哪里去了?
  12. DBeaver-调整字体
  13. bmfont使用心得
  14. word论文排版插件_word论文排版自动编号设置
  15. 教你如何安装小熊猫DEV-C++6.7.5版
  16. udacity深度学习--2. 深度学习简介--LESSON5 Jupyter notebook
  17. lotus中密送,抄送,正常发送的区别
  18. jQuery.on() 函数详解
  19. SpringCloud-Gateway网关统一登录鉴权+QQ第三方登录+Vue前后分离解决方案
  20. 普氏分析法的输入和输出实例,matlab图像处理

热门文章

  1. C语言学习笔记---断言函数assert()
  2. STM32F103自定义的printf函数的实现
  3. Java中数字格式化format方法
  4. python 近期用到的基础知识汇总(六)
  5. Python风格总结:错误和异常
  6. 构建之法阅读笔记(1)
  7. VR来了,科技的各行各业要如何做好准备?
  8. [精华][推荐]CAS SSO 实现单点登录实例源码
  9. 「SF图片上传不清晰」解决方案
  10. Oracle数据库的启动与关闭