`
k_lb
  • 浏览: 799024 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论
  • kitleer: 据我所知,国内有款ETL调度监控工具TaskCTL,支持ket ...
    kettle调度

对c#深拷贝和浅拷贝的理解

 
阅读更多

在c#中,浅拷贝和深拷贝的都是要同过clone方法才行吧,然而具体是深拷贝还是浅拷贝则看clone内部如何实现吧?浅拷贝其实就是一个对象的赋值吧,比如一个对象a,浅拷贝就是b=a;就可以实现浅拷贝了,如果是深拷贝的话将对象的数据真正的拷贝到新对象中,需要新建对象。为什么需要对象拷贝?直接使用工厂方法创建对象浅拷贝不行吗?可能的原因是在用工厂方法时,对每个工厂都要建立也是一个麻烦事,有时候还不如直接修改clone方法来的快。

以下内容转自:http://www.cnblogs.com/xugang/archive/2010/09/09/1822555.html

也许会有人这样解释C# 中浅拷贝与深拷贝区别:

浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝。

不能说它完全错误,但至少还不够严谨。比如:string 类型咋说?

其实,我们可以通过实践来寻找答案。

首先,定义以下类型:

int 、string 、enum 、struct 、class 、int[ ] 、string[ ]

代码如下:

//枚举
publicenummyEnum
{_1=1,_2=2}
//结构体
publicstructmyStruct
{
publicint_int;
publicmyStruct(inti)
{_int=i;}
}
//
classmyClass
{
publicstring_string;
publicmyClass(strings)
{_string=s;}
}
//ICloneable:创建作为当前实例副本的新对象。
classDemoClass:ICloneable
{
publicint_int=1;
publicstring_string="1";
publicmyEnum_enum=myEnum._1;
publicmyStruct_struct=newmyStruct(1);
publicmyClass_class=newmyClass("1");
//数组
publicint[]arrInt=newint[]{1};
publicstring[]arrString=newstring[]{"1"};
//返回此实例副本的新对象
publicobjectClone()
{
//MemberwiseClone:返回当前对象的浅表副本(它是Object对象的基方法)
returnthis.MemberwiseClone();
}
}

注意:

ICloneable 接口:支持克隆,即用与现有实例相同的值创建类的新实例。

MemberwiseClone 方法:创建当前 System.Object 的浅表副本。

接下来,构建实例A,并对实例A克隆产生一个实例B
然后,改变实例B的值,并观察实例A的值会不会被改变。

代码如下:

class浅拷贝与深拷贝
{
staticvoidMain(string[]args)
{
DemoClassA=newDemoClass();
//创建实例A的副本-->新对象实例B
DemoClassB=(DemoClass)A.Clone();
B._int=2;
Console.WriteLine("int\t\tA:{0}B:{1}",A._int,B._int);
B._string="2";
Console.WriteLine("string\tA:{0}B:{1}",A._string,B._string);
B._enum=myEnum._2;
Console.WriteLine("enum\t\tA:{0}B:{1}",(int)A._enum,(int)B._enum);
B._struct._int=2;
Console.WriteLine("struct\tA:{0}B:{1}",
A._struct._int,B._struct._int);
B._class._string="2";
Console.WriteLine("class\t\tA:{0}B:{1}",
A._class._string,B._class._string);
B.arrInt[0]=2;
Console.WriteLine("intArray\tA:{0}B:{1}",
A.arrInt[0],B.arrInt[0]);
B.arrString[0]="2";
Console.WriteLine("stringArray\tA:{0}B:{1}",
A.arrString[0],B.arrString[0]);
Console.ReadKey();
}
}

结果如下:

2010-09-08_221736

从最后的输出结果,我们得知:

对于内部的Class 对象和数组,则Copy 一份地址。[ 改变B 时,A也被改变了 ]

而对于其它内置的int / string / enum / struct / object 类型,则Copy 一份值。

有一位网友说:string 类型虽然是引用类型,但是很多情况下.Net 把string 做值类型来处理,我觉得string 应该也是按照值类型处理的。

这说明他对string 类型还不够了解。

可以肯定的是:string 一定是引用类型。那它为什么是深拷贝呢?

如果你看一下string 类型的源代码就知道了:

//表示空字符串。此字段为只读。
publicstaticreadonlystringEmpty;

答案就在于 string 是 readonly 的,当改变 string 类型的数据值时,将重新分配了内存地址。

下面引用一段网友的代码:Vseen[ Aloner ]的个人陋见:

publicclassStudent
{
//这里用“字段”,其实应当是属性。
publicstringName;
publicintAge;
//自定义类Classroom
publicClassroomClass;
}
浅拷贝:StudentA浅拷贝出StudentB,Name和Age拥有新的内存地址,但引用了同一个Classroom。
深拷贝:StudentA浅拷贝出StudentB,Name和Age拥有新的内存地址,并且A.Classroom的内存地址不等于B.Classroom。
其实俗点讲,有点像:
publicobjectClone()
{
StudentB=newStudent();
B.Name=this.Name;
B.Age=this.Age;
//浅拷贝
B.Class=this.Class;
//深拷贝
B.Class=newClassromm();
B.Class.Name=this.Class.Name;
B.Class.Teacher=this.Class.Teacher;
//根据情况,对Teacher 进行判定要进行的是深拷贝,还是浅拷贝。
}

浅拷贝:给对象拷贝一份新的对象。

浅拷贝的定义 —— 只对值类型(或string)类型分配新的内存地址。


深拷贝:给对象拷贝一份全新的对象。

深拷贝的定义 —— 对值类型分配新的内存地址,引用类型、以及引用类型的内部字段分配的新的地址。

我是这么定义的:浅拷贝,换汤不换药。

注意:

1、在 .NET 程序中,应该避免使用 ICloneable 接口。

因为通过该接口无法判断究竟是浅拷贝还是深拷贝,这会造成误解或误用。

2、深拷贝应该复制该对象本身及通过该对象所能到达的完整的对象图,浅拷贝只复制对象本身(就是该对象所表示的在堆中的一块连续地址中的内容)。

个人愚见:

Clone :深层拷贝,拷贝到了指针指向的内存块的值。

浅拷贝:仅仅拷贝了指针的内容。(只是给一个对象多起了个名字,所以,当改变拷贝的某个属性的时候,原对象的对应属性亦会改变)。


分享到:
评论

相关推荐

    浅拷贝和深拷贝深入理解(shallow copy VS deep copy)

    引言C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量,对于值类型变量,深拷贝和前拷贝都是通过赋值操作符号(=)实现,其效果一致,将对象中的值类型的字段拷贝到新的对象中.这个很容易理解。 本文重点...

    asp.net知识库

    我对J2EE和.NET的一点理解 难分难舍的DSO(一) InternalsVisibleToAttribute,友元程序集访问属性 Essential .NET 读书笔记 [第一部分] NET FrameWork的Collections支持 .NET的反射在软件设计上的应用 关于跨程序集...

    Linux 平台基于 Qt5 的网速浮窗.zip

    Linux 平台基于 Qt5 的网速浮窗

    手机游戏峡谷沼泽农田关卡地图Ai+EPS+PSD源文件.zip

    游戏开发资源,游戏UI,游戏GUI,游戏图标,PSD格式,XD格式,PNG下载,源文件,可编辑下载,游戏购物充值界面,宝石,图标,PS格式,AI格式等,游戏APP

    上市公司-企业资本结构动态调整数据及代码(2001-2022年).txt

    数据存放网盘,txt文件内包含下载链接及提取码,永久有效。 样例数据及详细介绍参见文章:https://blog.csdn.net/li514006030/article/details/138324717

    Git 常用命令手册大全

    Git 是一个开源的分布式版本控制系统,它允许你跟踪代码的更改,并且可以与他人合作开发项目。附件中是一些常用的 Git 命令。 这些命令覆盖了 Git 的基本操作,包括初始化、克隆、提交、分支管理、合并、查看状态和历史、远程仓库操作等。根据你的具体需求,可能还需要学习更多的命令和 Git 的高级用法。 文件绿色安全,仅供学习交流使用,欢迎大家下载学习交流!

    中科大2021秋《机器学习概论》课程资源.zip

    机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。它专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。机器学习是人工智能的核心,是使计算机具有智能的根本途径。 机器学习的发展历程可以追溯到20世纪50年代,当时Arthur Samuel在IBM开发了第一个自我学习程序,一个西洋棋程序,这标志着机器学习的起步。随后,Frank Rosenblatt发明了第一个人工神经网络模型——感知机。在接下来的几十年里,机器学习领域取得了许多重要的进展,包括最近邻算法、决策树、随机森林、深度学习等算法和技术的发展。 机器学习有着广泛的应用场景,如自然语言处理、物体识别和智能驾驶、市场营销和个性化推荐等。通过分析大量的数据,机器学习可以帮助我们更好地理解和解决各种复杂的问题。例如,在自然语言处理领域,机器学习技术可以实现机器翻译、语音识别、文本分类和情感分析等功能;在物体识别和智能驾驶领域,机器学习可以通过训练模型来识别图像和视频中的物体,并实现智能驾驶等功能;在市场营销领域,机器学习可以帮助企业

    游戏道具3D立体blender模型图标素材-3d Game Asset Icon Vol.1.zip

    游戏开发资源,游戏UI,游戏GUI,游戏图标,PSD格式,XD格式,PNG下载,源文件,可编辑下载,游戏购物充值界面,宝石,图标,PS格式,AI格式等,游戏APP

    K1213-Q版游戏UI界面.zip

    游戏开发资源,游戏UI,游戏GUI,游戏图标,PSD格式,XD格式,PNG下载,源文件,可编辑下载,游戏购物充值界面,宝石,图标,PS格式,AI格式等,游戏APP

    百问网linux桌面GUI,基于LVGL 8.x。.zip

    百问网linux桌面GUI,基于LVGL 8.x。

    HTML5小游戏源码下载网页版游戏JS小游戏-塔防源码.zip

    HTML5小游戏源码下载,JS小游戏源码下载,坦克大战,驴子跳,连连看,俄罗斯方块,圈泡泡,塔防,太空战舰,愤怒的小鸟,植物大战僵尸,水果忍者,扫雷,超级玛丽,打地鼠,坦克大战,麻将等JS小游戏源码下载,游戏开发教程,网页游戏,本地直接打开就可以玩。

    2022年 【30页】外部环境边际改善,AIGC搭建元宇宙内容生态.zip

    2022年 【30页】外部环境边际改善,AIGC搭建元宇宙内容生态.zip

    node-v10.15.3-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v6.11.1-sunos-x64.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Support 客户关系管理 - SAS 支持.pdf

    Support 客户关系管理 - SAS 支持.pdf

    node-v6.12.1-sunos-x64.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    机械设计PF-1315反击式破碎机sw14可编辑非常好的设计图纸100%好用.zip

    机械设计PF-1315反击式破碎机sw14可编辑非常好的设计图纸100%好用.zip

    ATMEGA328P+CH340C arduino-nano最小系统开发板AD09设计硬件(原理图+PCB)文件.zip

    ATMEGA328P+CH340C arduino_nano最小系统板ALTIUM设计硬件原理图+PCB文件,硬件采用2层板设计,大小为8x10mm, 包括完整的ALTIUM设计硬件原理图和PCB文件,可以做为你的设计参考。

    源代码-160.es免费资源网程序.zip

    源代码-160.es免费资源网程序.zip

    用Python来抓取一个新闻网站上的文章标题、链接、发布时间和内容

    在这个爬虫开发案例中,我们将使用Python的requests库和BeautifulSoup库来抓取一个新闻网站(如https://news.example.com)上的文章标题、链接、发布时间和内容。 代码解释 导入requests和BeautifulSoup库。 定义get_article_list函数,接收一个URL参数,用于获取文章列表。 使用requests.get()方法发送GET请求,获取网页内容。 使用BeautifulSoup解析网页内容,提取文章标题、链接和发布时间。 将提取到的文章信息存储在一个字典列表中,并返回。 定义get_article_content函数,接收一个URL参数,用于获取文章内容。 使用requests.get()方法发送GET请求,获取网页内容。 使用BeautifulSoup解析网页内容,提取文章内容。 返回提取到的文章内容。 在主函数main中调用get_article_list函数,遍历文章列表并输出标题、链接、发布时间和内容。 注意:请将示例中的https://news.example.com替换为您要抓取的实际新闻网站URL。在

Global site tag (gtag.js) - Google Analytics