浅谈.net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力。所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的
基本概念:
浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个对象。大部分的引用类型,实现的都是浅拷贝,引用类型对象之间的赋值,就是复制一个对象引用地址的副本,而指向的对象实例仍然是同一个。
深拷贝:指对象的子段被拷贝,同时字段引用的对象也进行了拷贝。深拷贝创建的是整个源对象的结构,拷贝对象和原对象相互独立,不共享任何实例数据,修改一个对象不会影响到另一个对象。值类型之间的赋值操作,执行的就是深拷贝。
基本概念之参考代码:
class Program
{
static void Main(string[] args)
{
Student s1 = new Student("li", 23);
//浅拷贝
Student s2 = s1;
s2.Age = 27;
s1.ShowInfo();//li's age is 27
//深拷贝
int i = 12;
int j = i;
j = 22;
Console.WriteLine(i);//12
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”的值。
深浅拷贝的实现:
public object Clone()
{
return this.MemberwiseClone();
}
MemberwiseClone:创建一个浅表副本。过程是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用对象。
参考代码:
class Program
{
static void Main(string[] args)
{
ClassA ca = new ClassA();
ca.value = 88;
ClassA ca2 = new ClassA();
ca2 = (ClassA)ca.Clone();
ca2.value = 99;
Console.WriteLine(ca.value + "-----" + ca2.value);//88---99
ClassB cb = new ClassB();
cb.Member.value = 13;
ClassB cb2 = (ClassB)cb.Clone();
cb2.Member.value = 7;
Console.WriteLine(cb.Member.value.ToString() + "------" + cb2.Member.value.ToString());//浅拷贝:7---7 深拷贝:13----7
Console.Read();
}
}
public class ClassA : ICloneable
{
public int value = 0;
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 = 3;
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 = 1;
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 = { 2, 3, 4, 5 };
int[] numbersCopy = new int[5];
numbers.CopyTo(numbersCopy, 0);
numbersCopy[2] = 0;
int[] numbers1 = { 2, 3, 4, 5 };
int[] numbersClone1 = (int[])numbers1.Clone();
numbersClone1[2] = 0;
Console.Write(numbers[2] + "---" + numbersCopy[2]);//4---0
Console.Write(numbers1[2] + "---" + numbersClone1[2]);//4--0
//数组的复制也就是引用传递,指向的是同一个地址
int[] numbers2 = { 2, 3, 4, 5 };
int[] numbers2Copy = numbers2;
numbers2Copy[2] = 0;
Console.Write(numbers2[2]);//0
Console.Write(numbers2Copy[2]);//0
Console.Read();
}
}
浅谈.net平台下深拷贝和浅拷贝的更多相关文章
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- .net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的. ...
- 浅谈python 复制(深拷贝,浅拷贝)
博客参考:点击这里 python中对象的复制以及浅拷贝,深拷贝是存在差异的,这儿我们主要以可变变量来演示,不可变变量则不存在赋值/拷贝上的问题(下文会有解释),具体差异如下文所示 1.赋值: a=[1 ...
- java基础(十七)----- 浅谈Java中的深拷贝和浅拷贝 —— 面试必问
假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...
- 浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍
浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍 前记 自己是搞编程的,首先我是一个菜鸟,接触计算机这么久了,感觉很多计算机方面的技术和知识朦朦胧胧.模模糊糊,貌似有些贻笑大方了:所 ...
- 浅谈C#中的深拷贝(DeepCopy)与浅拷贝(MemberwiseClone)
场景:MVVM模式中数据双向绑定,想实现编辑.保存.撤销操作时也双向绑定了,不能实现撤销操作. 后来通过搜索找到了继承IEditableObject接口实现撤销操作,但是对其中使用了Memberwis ...
- 浅谈python中的赋值、浅拷贝与深拷贝:
1.赋值----------是对原对象的引用,指向同一片内存地址 浅拷贝和深拷贝对于容器类型对象才有意义 2.浅拷贝----------对于一个对象的顶层进行拷贝 浅拷贝有三种方式: (1)切片 (2 ...
- 浅谈SDN架构下的运维工作
导读 目前国内的网络运维还处于初级阶段,工作人员每天就像救火一样,天天疲于奔命.运维人员只能埋头查找系统运行的日志,耗时耗力,老眼昏花不说,有时候忙了半天还一无所获,作为运维工程师的你,有木有遇到过类 ...
随机推荐
- Codeforces D. Giving Awards 412 题解
就是依照一定顺序输出排序. 比方a欠b的钱就不能先输出a然后输出b. 本题的技巧就是.要求的是不能先输出a然后输出b,可是能够先输出b然后输出a. 故此能够依照a欠b的钱的关系.建立图,然后DFS深度 ...
- 利用Teensy进行EM410x卡模拟以及暴力破解EM410X类门禁系统可行性猜想
前些天Open入手了Teensy++2.0模拟EM410X,并且针对EM410X的门禁进行了一次暴力破解测试,以下就是相关代码以及内容. 什么是低频?什么是EM410x? 首先,我不得不再次提一下那些 ...
- RenderMonkey基本使用方法【转】
RenderMonkey基本使用方法 楔子: 差不多从年中开始由于工作需要,开始研究Direct3D,这是继大二开始自学DX开始,睽违了6年后再重新学习DX.虽然时间很久了,但是幸亏还是有点基础,所以 ...
- Yahoo 股票数据抓取
Yahoo提供日线级别的历史数据,包括国内外各交易所的数据,可以写爬虫抓取数据做简单的分析. api基本格式如下: http://ichart.yahoo.com/table.csv?s=<st ...
- IE8兼容<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
转自:http://nicyea.iteye.com/blog/719007 前言 X-UA-Compatible是针对ie8新加的一个设置,对于ie8之外的浏览器是不识别的,这个区别与 conten ...
- 【玩转cocos2d-x之三十九】Cocos2d-x 3.0截屏功能集成
3.0的截屏和2.x的截屏基本上同样.都是利用RenderTexture来处理,在渲染之前调用call函数,然后调用Cocos的场景visit函数对其进行渲染,渲染结束后调用end函数就可以.仅仅是3 ...
- Django——META内部类选项
Django 模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性.以下对此作一总结: abstract 这个属性是定义当前的模型类是不是一个抽象类.所谓抽象类是不会对应 ...
- import * as obj from 'xx'
import * as obj from 'xx' 这种写法是把所有的输出包裹到obj对象里 例如: xx里中: export function hello(){ return '我是hello 内 ...
- Activity设置切换动画时黑屏问题的解决
//当这么设置的时候.打开Acticity的时候会黑屏一下 overridePendingTransition(R.anim.activity_open,0); //改成例如以下代码 完美解决这个问题 ...
- hiredis中异步的实现小结
hiredis中异步的实现小结 原文: http://blog.csdn.net/l1902090/article/details/3858... 时间: 2014-08-15 前言 一般情况下我们使 ...