.net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力。所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的。
基本概念:
浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个对象。大部分的引用类型,实现的都是浅拷贝,引用类型对象之间的赋值,就是复制一个对象引用地址的副本,而指向的对象实例仍然是同一个。
深拷贝:指对象的子段被拷贝,同时字段引用的对象也进行了拷贝。深拷贝创建的是整个源对象的结构,拷贝对象和原对象相互独立,不共享任何实例数据,修改一个对象不会影响到另一个对象。值类型之间的赋值操作,执行的就是深拷贝。
基本概念之参考代码:
- class Program
- {
- static void Main(string[] args)
- {
- Student s1 = new Student("li", );
- //浅拷贝
- Student s2 = s1;
- s2.Age = ;
- s1.ShowInfo();//li's age is 27
- //深拷贝
- int i = ;
- int j = i;
- j = ;
- Console.WriteLine(i);//
- Console.Read();
- }
- }
- class Student
- {
- public string Name;
- public int Age;
- public Student(string name, int age)
- {
- Name = name;
- Age = age;
- }
- public void ShowInfo()
- {
- Console.WriteLine("{0}'s age is {1}", Name, Age);
- }
- }
分析:
在上例中,实例s2对s1进行了浅拷贝,对s2中的Age字段进行更改,继而影响实例s1中的Age字段。
深拷贝中,仅仅是值类型间简单的赋值,对“j”做出的更改不会更改“i”的值。
注:上述实例中的“浅拷贝”和“深拷贝”其实都和浅拷贝、深拷贝没有关系(因为它们都没有实现Clone),仅仅是为了说明浅拷贝和深拷贝的效果。
深浅拷贝的实现:
public object Clone()
{
return this.MemberwiseClone();
}
MemberwiseClone:创建一个浅表副本。过程是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用对象。
参考代码:
- class Program
- {
- static void Main(string[] args)
- {
- ClassA ca = new ClassA();
- ca.value = ;
- ClassA ca2 = new ClassA();
- ca2 = (ClassA)ca.Clone();
- ca2.value = ;
- Console.WriteLine(ca.value + "-----" + ca2.value);//88---99
- ClassB cb = new ClassB();
- cb.Member.value = ;
- ClassB cb2 = (ClassB)cb.Clone();
- cb2.Member.value = ;
- Console.WriteLine(cb.Member.value.ToString() + "------" + cb2.Member.value.ToString());//浅拷贝:7---7 深拷贝:13----7
- Console.Read();
- }
- }
- public class ClassA : ICloneable
- {
- public int value = ;
- public object Clone()
- {
- return this.MemberwiseClone();
- }
- }
- public class ClassB : ICloneable
- {
- public ClassA Member = new ClassA();
- public object Clone()
- {
- //浅拷贝
- return this.MemberwiseClone();
- //深拷贝
- ClassB obj = new ClassB();
- obj.Member = (ClassA)Member.Clone();
- return obj;
- }
- }
分析:
上例中,ca2复制ca对象,实现了深度拷贝。结果如同代码中显示:ca2中值类型字段的改变并不影响ca中的字段。
在类ClassB中,引用类型成员Member,如果用ClassA中的clone方法实现则仅仅实现的是浅拷贝,在上述参考代码中能够看出:对cb2的member的改变影响着cb。但是当使用参考代码中的深度拷贝后,对cb2的member的改变则不会影响着cb。
在网上找到一个综合的例子,有对比的来进行解释深浅拷贝:
实例1:
- public class Sex:ICloneable
- {
- private string _PSex;
- public string PSex
- {
- set{ _PSex = value;}
- get { return _PSex; }
- }
- //public object Clone()
- //{
- // return this.MemberwiseClone();
- //}
- }
- public class Person : ICloneable
- {
- private Sex sex = new Sex();
- public int aa = ;
- public string pSex
- {
- set { sex.PSex = value; }
- get { return sex.PSex; }
- }
- private string _PName;
- public string PName
- {
- set { this._PName = value; }
- get { return this._PName; }
- }
- public void ShowPersonInfo()
- {
- Console.WriteLine("-------------------------");
- Console.WriteLine("Name:{0} Sex:{1}", _PName, this.pSex);
- Console.WriteLine("-------------------------");
- Console.WriteLine(this.aa);
- }
- //浅拷贝
- public object Clone()
- {
- return this.MemberwiseClone();
- }
- //深拷贝
- public object DeepClone()
- {
- Person newP = new Person();
- newP.PName = this._PName;
- newP.pSex = this.pSex;
- return newP;
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("原对象:");
- Person p = new Person();
- p.PName = "Lee";
- p.pSex = "男";
- p.ShowPersonInfo();//原对象:lee 男 3
- //浅拷贝
- Person copy = (Person)p.Clone();
- //深拷贝
- Person dcopy = (Person)p.DeepClone();
- Console.WriteLine("修改后的原对象:");
- p.PName = "Zhao";
- p.pSex = "女";
- p.aa = ;
- p.ShowPersonInfo();//zhao 女 1
- Console.WriteLine("修改后的浅拷贝对象:");
- copy.ShowPersonInfo();//lee 女 3
- Console.WriteLine("修改后的深拷贝对象:");
- dcopy.ShowPersonInfo();//lee 男 3
- Console.WriteLine("直接拷贝对象:");
- Person PP = p;
- PP.ShowPersonInfo();//zhao 女 1
- Console.ReadLine();
- }
- }
分析:
首先需指出,上例中在类Sex中,加入Clone方法和不加对实例中运算结果没有影响。
类Person中,引用类型但却是string类型的PName字段,引用类型pSex字段,值类型aa。
初始值:lee 男 3 (先进行深浅拷贝)
修改值:zhao 女 1
浅拷贝值:lee 女 3
深拷贝值:lee 男 3
直接拷贝值:赵 女 1
结果:上述可以说是对深浅拷贝中经常遇到的几种类型做出总结和对比,相信在一番体悟后可以学到一些知识。
实例2:
- class Program
- {
- static void Main(string[] args)
- {
- int[] numbers = { , , , };
- int[] numbersCopy = new int[];
- numbers.CopyTo(numbersCopy, );
- numbersCopy[] = ;
- int[] numbers1 = { , , , };
- int[] numbersClone1 = (int[])numbers1.Clone();
- numbersClone1[] = ;
- Console.Write(numbers[] + "---" + numbersCopy[]);//4---0
- Console.Write(numbers1[] + "---" + numbersClone1[]);//4--0
- //数组的复制也就是引用传递,指向的是同一个地址
- int[] numbers2 = { , , , };
- int[] numbers2Copy = numbers2;
- numbers2Copy[] = ;
- Console.Write(numbers2[]);//
- Console.Write(numbers2Copy[]);//
- Console.Read();
- }
- }
暂不做分析,认真领悟。
引用:
.net平台下深拷贝和浅拷贝的更多相关文章
- 浅谈.net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的 ...
- java对象的克隆以及深拷贝与浅拷贝
一.为什么要使用克隆 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也 ...
- Objective-C中的深拷贝和浅拷贝
在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...
- $.extend()的深拷贝和浅拷贝详细讲解
版权声明:作者原创,转载请注明出处! 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 描述: 将两个或更多对象的内容合并到第一个对象 ...
- C++的深拷贝与浅拷贝
对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面是一个类对象拷贝的简单例子. #i ...
- [C#进阶系列]专题一:深入解析深拷贝和浅拷贝
一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...
- C++拷贝构造函数(深拷贝,浅拷贝)
对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #i ...
- python 深拷贝与浅拷贝
浅拷贝的方式有: lst=[1,2,3] (1)直接赋值: lst_cp = lst (2)for循环遍历生成:lst_cp= [i for i in lst] (3)copy模块下,copy.cop ...
- python 中 深拷贝和浅拷贝的理解
在总结 python 对象和引用的时候,想到其实 对于python的深拷贝和浅拷贝也可以很好对其的进行理解. 在python中,对象的赋值的其实就是对象的引用.也就是说,当创建一个对象,然后赋给另外一 ...
随机推荐
- openstack-L版安装
参照官方install document: http://docs.openstack.org/liberty/install-guide-rdo/ 实验环境:centos7.2 桥接: 192.16 ...
- java密码验证正则表达式校验
,正则表达式就是记录文本规则的代码.php密码验证正则表达式(8位长度限制)<?php //密码验证 $password = "zongzi_Abc_oo13a2"; $n ...
- [转].net自定义验证控件CustomValidator的使用
本文转自:http://tech.cncms.com/web/aspnet/96310.html CustomValidator验证控件,可以自定义验证函数,实现其它几个验证控件不能实现的验证规则,最 ...
- poj 2186 tarjan求强连通分量
蕾姐讲过的例题..玩了两天后才想起来做 貌似省赛之后确实变得好懒了...再努力两天就可以去北京玩了! 顺便借这个题记录一下求强连通分量的算法 1 只需要一次dfs 依靠stack来实现的tarjan算 ...
- Nginx 报错: nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory) 的解决方法
今天测试域名访问不了,登陆 Linux(Ubuntu)重启Nginx: nginx -s reload 结果报错: nginx: [error] open() : No such file or di ...
- PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [1] 单例模式连接数据库
单例模式 单例模式三大原则: ① 构造函数需要标记为非 public (防止外部使用 new 操作符创建对象),单例类不能在其他类中实例化,只能被自身实例化: ② 拥有一个保存类的实例的静态成员变量 ...
- PHP+jQuery 注册模块的改进之一:验证码存入SESSION
/* ******* Date:2014-09-28 ******* Author:小dee ******* Blog:http://www.cnblogs.com/dee0912/*/ 对上一篇博文 ...
- 综合支撑【恶灵附身 Psycho Break】的世界观的概念艺术
综合支撑[恶灵附身 Psycho Break]的世界观的概念艺术 三上真司监督提出的,是对着重表现讲述内心恐怖的哪个世界观的创作和统一做了很大贡献的概念艺术. 这里以他经手的艺术为例,来看看稀少的恐 ...
- PHP面向对象程序设计的61条黄金法则
PHP面向对象程序设计的61条黄金法则 你不必严格遵守这些原则,违背它们也不会被处以宗教刑罚.但你应当把这些原则看成警铃,若违背了其中的一条,那么警铃就会响起 . ----- Arthur J.R ...
- nRF51822之pstorage使用摘要
https://devzone.nordicsemi.com/question/15271/how-can-i-write-10kb-of-data-to-internal-flash/?answer ...