浅谈C#浅拷贝和深拷贝
近来爱上一本书《编写高质量代码,改善C#程序的157个建议》,我想很多人都想编写高质量的代码,因为我们不仅仅是码农,更是一名程序员。
从今天开始,我将每天和大家分享这本书中的内容,并加上自己的理解,希望可以帮助到更多和我一样盲目的程序员们。
今天我们谈谈C#中的对象拷贝问题;
所谓的对象拷贝,其实就是为对象创建副本,C#中将拷贝分为两种,分别为浅拷贝和深拷贝;
所谓浅拷贝就是将对象中的所有字段复制到新的副本对象中;浅拷贝对于值类型与引用类型的方式有区别,值类型字段的值被复制到副本中后,在副本中的修改不会影响源对象对应的值;然而对于引用类型的字段被复制到副本中的却是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值被修改后,源对象的值也将被修改。
深拷贝也同样是将对象中的所有字段复制到副本对象中,但是,无论对象的值类型字段或者引用类型字段,都会被重新创建并复制,对于副本的修改,不会影响到源对象的本身;
当然,无论是哪种拷贝,微软都建议使用类型继承ICloneable接口的方式明确告诉调用者,该对象是否可用被拷贝。当然了,ICloneable接口只提供了一个声明为Clone的方法,我们可以根据需求在Clone的方法内实现浅拷贝或者是深拷贝,下面我们进行一段浅拷贝的案例,代码如下
class Student : ICloneable
{
public string IDCode { get; set; } public int Age { get; set; } public Grent Grent { get; set; } #region 拷贝主体
public object Clone()
{
return this.MemberwiseClone();
//throw new NotImplementedException();
}
#endregion } class Grent
{
public string Name { get; set; } public override string ToString()
{
return this.Name;
}
}
调用
Student stu1 = new Student()
{
IDCode = "lily",
Age = ,
Grent = new Grent() { Name="五年三班"}
};
Student stu2 = stu1.Clone() as Student;
if (stu2 == null) {
Console.WriteLine("转换失败");
Console.ReadKey();
return;
} Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString()); Console.WriteLine("重新为stu1赋值");
stu1.IDCode = "Anagle";
stu1.Age += ;
stu1.Grent.Name = "六年二班";
Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString());
Console.ReadKey();
输出结果为:
lily
24
五年三班
重新为stu1赋值
lily
24
六年二班
aaarticlea/png;base64,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" alt="" />
这里我们需要注意一点Student中的IDCode属性是string类型,理论上string类型是引用类型,但是由于该引用类型的特殊性,Object.MemberwiseClone方法仍旧为他创建了副本,也就是说,在浅拷贝过程中,我们应该将字符串看成值类型;
因为Student中的Grent是引用类型,所以在stu1中的Grent的Name被改变的同时,副本stu2中的Grent的Name也同样被改变。
Student的深拷贝有多钟实现方法,最简单的方法是手动对字段诼个赋值,但是这种方法容易出错,也就是说,如果类型的字段发生变化或有增减时,那么该拷贝方法也就要发生相应的变化,所以,建议使用序列化的形式来进行深拷贝。实现代码如下
[Serializable]
class Student : ICloneable
{
public string IDCode { get; set; } public int Age { get; set; } public Grent Grent { get; set; } #region 拷贝主体
/// <summary>
/// 深度拷贝
/// </summary>
/// <returns></returns>
public Student DeepClone() {
using (Stream objectStream = new MemoryStream()) {
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(objectStream, this);
objectStream.Seek(,SeekOrigin.Begin);
return formatter.Deserialize(objectStream) as Student;
}
} public object Clone()
{
return this.MemberwiseClone();
}
#endregion }
调用DeepClone方法
Student stu1 = new Student()
{
IDCode = "lily",
Age = ,
Grent = new Grent() { Name="五年三班"}
};
Student stu2 = stu1.DeepClone() as Student;
if (stu2 == null) {
Console.WriteLine("转换失败");
Console.ReadKey();
return;
} Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString()); Console.WriteLine("重新为stu1赋值");
stu1.IDCode = "Anagle";
stu1.Age += ;
stu1.Grent.Name = "六年二班";
Console.WriteLine(stu2.IDCode);
Console.WriteLine(stu2.Age);
Console.WriteLine(stu2.Grent.ToString());
Console.ReadKey();
输出结果为:
lily
24
五年三班
重新为stu1赋值
lily
24
五年三班
aaarticlea/png;base64,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" alt="" />
这次我们看到的结果已经很明显了,深拷贝后,源对象的重新赋值与修改将不再导致副本对象被修改,这样将很好的控制住引用类型的拷贝问题。
浅谈C#浅拷贝和深拷贝的更多相关文章
- 浅谈java浅拷贝和深拷贝
前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.深拷 ...
- 浅谈Javascript 浅拷贝和深拷贝的理解
javascript中存储对象都是存地址的. 浅拷贝:浅拷贝是都指向同一块内存区块,浅拷贝共用同一内存地址,你改值我也变.如果拷贝的对象里面的值是一个对象或者数组,它就是浅拷贝,拷贝的知识引用地址. ...
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 浅谈python 复制(深拷贝,浅拷贝)
博客参考:点击这里 python中对象的复制以及浅拷贝,深拷贝是存在差异的,这儿我们主要以可变变量来演示,不可变变量则不存在赋值/拷贝上的问题(下文会有解释),具体差异如下文所示 1.赋值: a=[1 ...
- 浅谈C#中的深拷贝(DeepCopy)与浅拷贝(MemberwiseClone)
场景:MVVM模式中数据双向绑定,想实现编辑.保存.撤销操作时也双向绑定了,不能实现撤销操作. 后来通过搜索找到了继承IEditableObject接口实现撤销操作,但是对其中使用了Memberwis ...
- 浅谈.net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的 ...
- java基础(十七)----- 浅谈Java中的深拷贝和浅拷贝 —— 面试必问
假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...
- 浅谈JS中的浅拷贝与深拷贝
前端工程师应该都比较熟悉浅拷贝和深拷贝的概念,在日常业务代码的过程中,特别是做数据处理的时候,经常行的会遇到,比如如何在不修改原对象的基础上,重新生成一个一模一样的对象,加以利用,又或是,如何巧妙地运 ...
随机推荐
- eclipse下python的selenium自动化环境的搭建
前提:安装python,我用的2.7.8版本,并在环境变量path里设置;E:\Python1.解压setuptools(Python包管理工具),cmd到目录执行python setup.py in ...
- lintcode : 跳跃游戏
跳跃游戏 给出一个非负整数数组,你最初定位在数组的第一个位置. 数组中的每个元素代表你在那个位置可以跳跃的最大长度. 判断你是否能到达数组的最后一个位置. 样例 A = [2,3,1,1,4],返回 ...
- Java多线程-线程的调度(守护线程)
本文转自http://www.cnblogs.com/linjiqin/p/3210004.html 感谢作者 守护线程与普通线程写法上基本没啥区别,调用线程对象的方法setDaemon(true), ...
- iOS开发--正则表达式
目录[-] 正则表达式简单语法总结 一.什么是正则表达式 二.正则表达式的基础语法 1.字面值 2.特殊字符(元字符) (1)句号 (2)字符类([]) (3)区间符号(-) (4)取反符号(^) ( ...
- Spring AOP基础知识
Spring AOP使用动态代理技术在运行期织入增强的代码,两种代理机制包括:一是基于JDK的动态代理,另一种是基于CGLib的动态代理.之所以需要两种代理机制,很大程度上是因为JDK本身只提供接口的 ...
- 局部敏感哈希Locality Sensitive Hashing(LSH)之随机投影法
1. 概述 LSH是由文献[1]提出的一种用于高效求解最近邻搜索问题的Hash算法.LSH算法的基本思想是利用一个hash函数把集合中的元素映射成hash值,使得相似度越高的元素hash值相等的概率也 ...
- 乙醇脱氢酶力场文件的处理(含ZN,NAD,乙醇)
很多蛋白质在行驶生物催化反应(如ATP水解,氨基酸的乙酰化,CoA的去乙酰化,甲基化等等)都需要金属离子(Mg,Zn,Ca等等)的参与,换句话说,金属离子对蛋白功能是必须的.模拟金属酶体系,现在也是分 ...
- CListView虚拟列表
首先说下虚拟列表出现的原因: 数据量比较小的时候,对于CListView控件可以直接使用InsertItem并配合SetItemText函数来插入并修改数据.这样操作很直接. 但是,如果数据量比较大了 ...
- Kruskal
算法描述:克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge). 算法过程: 1.将图各边按照权值进行排序 2找出权值最小的边,(条件 ...
- 字符串 —— String?StringBuffer?StringBuilder?
字符串常用的操作就是拼接,特别是SQL语句的拼接. 做了个简单的试验,它们之间的差别惊人! StringBuffer: public void testStringBuffer() { long st ...