C# 浅拷贝与深拷贝(复制)
在有些时候,我们需要从数据库读取数据填充对象或从硬盘读取文件填充对象,但是这样做相对耗时。这时候我们就想到了对象的拷贝。本文即以实例形式解析了C#浅拷贝和深拷贝的用法。
C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量。对于前者,copy是属于全盘复制;而对后者,一般的copy只是浅copy,相当于只传递一个引用指针一样。因此 对于后者进行真正copy的时候,也是最费事的,具体的说,必须为其实现ICloneable接口中提供的Clone方法。
一、浅拷贝
1.什么是"浅拷贝":
当针对一个对象浅拷贝的时候,对于对象的值类型成员,会复制其本身,对于对象的引用类型成员,仅仅复制对象引用,这个引用指向托管堆上的对象实例。
例如:有一个对象,包含引用类型的类成员和值类型的struct成员
即:Cinema包含 引用类型成员Room和值类型成员Film。
public class Room
{
public int _maxSeat; public Room(int maxSeat)
{
this._maxSeat = maxSeat;
}
} public struct Film
{
public string _name; public Film(string name)
{
this._name = name;
}
} public class Cinema
{
public Room _room;
public Film _film; public Cinema(Room room, Film film)
{
this._room = room;
this._film = film;
} public object Clone()
{
return MemberwiseClone(); //对引用类型实施浅复制
}
}
2.测试拷贝后的效果
①打印出原先对象 拷贝前值类型和引用类型成员的值
②对原先对象拷贝,打印出复制对象值类型和引用类型成员的值
③改变原先对象的值,再次打印原先对象的值类型和引用类型成员的值
④再次打印复制对象值类型和引用类型成员的值
static void Main(string[] args)
{
Room room1 = new Room();
Film film1 = new Film("家园防线");
Cinema cinema1 = new Cinema(room1, film1);
Cinema cinema2 = (Cinema)cinema1.Clone();
Console.WriteLine("拷贝之前,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name,cinema1._room._maxSeat); Console.WriteLine("拷贝之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat); //修改拷贝之前引用类型的字段值
cinema1._film._name = "极品飞车";
cinema1._room._maxSeat = ; Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);
Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat); Console.ReadKey();
}
运行结果如下:
分析:
浅拷贝关键点是对引用类型拷贝的是对象引用,这个引用指向托管堆上的对象实例。改变原对应引用类型的值,会影响到复制对象。
二、深拷贝
1.什么是"深拷贝"
对引用成员指向的对象也进行复制,在托管堆上赋值原先对象实例所包含的数据,再在托管堆上创建新的对象实例。
2.通过对每个对象成员进行复制进行深拷贝
public object Clone()
{
Room room = new Room();
room._maxSeat = this._room._maxSeat;//复制当前引用类型成员的值到新对象 </span>
Film film = this._film; //值类型直接赋值
Cinema cinema = new Cinema(room, film);
return cinema;
}
3.也可以通过序列化和反序列化进行深拷贝
public object Clone1()
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, this); //复制到流中
ms.Position = ;
return (bf.Deserialize(ms));
}
4.采用序列化和反序列化深拷贝,但必须把所有的类打上[Serializable],测试代码如下:
[Serializable]
public class Room
{
public int _maxSeat; public Room()
{} public Room(int maxSeat)
{
this._maxSeat = maxSeat;
}
} [Serializable]
public struct Film
{
public string _name; public Film(string name)
{
this._name = name;
}
} [Serializable]
public class Cinema
{
public Room _room;
public Film _film; public Cinema(Room room, Film film)
{
this._room = room;
this._film = film;
} //浅拷贝
//public object Clone()
//{
// return MemberwiseClone(); //对引用类型实施浅复制
//} //深拷贝 对每个对象成员进行复制
public object Clone()
{
Room room = new Room();
room._maxSeat = this._room._maxSeat;//复制当前引用类型成员的值到新对象
Film film = this._film; //值类型直接赋值
Cinema cinema = new Cinema(room, film);
return cinema;
} //使用序列化和反序列化进行复制
public object Clone1()
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, this); //复制到流中
ms.Position = ;
return (bf.Deserialize(ms));
}
}
static void Main(string[] args)
{
Room room1 = new Room();
Film film1 = new Film("家园防线");
Cinema cinema1 = new Cinema(room1, film1);
Cinema cinema2 = (Cinema)cinema1.Clone1();
Console.WriteLine("拷贝之前,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name,cinema1._room._maxSeat); Console.WriteLine("拷贝之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat); //修改拷贝之前引用类型的字段值
cinema1._film._name = "极品飞车";
cinema1._room._maxSeat = ; Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);
Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat); Console.ReadKey();
}
C# 浅拷贝与深拷贝(复制)的更多相关文章
- java List复制:浅拷贝与深拷贝
Java的拷贝可以分为三种:浅拷贝(Shallow Copy).深拷贝(Deep Copy).延迟拷贝(Lazy Copy). 在java中除了基本数据类型之外(int,long,short等),还存 ...
- Javascript/js 的浅拷贝与深拷贝(复制)学习随笔
js变量的数据类型值分基本类型值和引用类型值. 在ES6(ECMAScript6)以前,基本数据类型包括String.Number.Boolean.Undefined.Null. 基本类型值的复制(拷 ...
- 【转】Python中的赋值、浅拷贝、深拷贝介绍
这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下 和很多语言一样,Python中 ...
- 渐析java的浅拷贝和深拷贝
首先来看看浅拷贝和深拷贝的定义: 浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值,这个方式被称为浅拷贝. 深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所 ...
- 关于JavaScript的浅拷贝和深拷贝
在 JS 中有一些基本类型像是Number.String.Boolean,而对象就是像这样的东西{ name: 'Larry', skill: 'Node.js' },对象跟基本类型最大的不同就在于他 ...
- c#中浅拷贝和深拷贝的理解
c#中拷贝有浅拷贝和深拷贝之分. 例如对象A,其中有值类型字段和引用类型字段: 1.浅拷贝: 对于值类型字段,直接逐位复制到新拷贝的副本对象中,修改副本的字段的值,不会影响源对象中字段的值: 对于引用 ...
- C#浅拷贝与深拷贝区别
也许会有人这样解释C# 中浅拷贝与深拷贝区别: 浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝. 不能说它完全错误,但至少还不够严谨.比如:string 类型咋说? 其实,我们可以通过实践来寻找答案 ...
- IOS的浅拷贝和深拷贝
什么是深拷贝和浅拷贝 浅拷贝:就是指针的复制,拷贝的指针跟原指针指向内存中的同一个位置的对象.至于对象的引用计数值是否+1,就是看拷贝的指针赋给给的变量是Strong类型的,还是week类型的. 如果 ...
- 关于python中赋值、浅拷贝、深拷贝之间区别的深入分析
当重新学习了计算机基础课程<数据结构和算法分析>后再来看这篇自己以前写的博文,发现错误百出.python内置数据类型之所以会有这些特性,归根结底是它采用的是传递内存地址的方式,而不是传递真 ...
随机推荐
- MyBatis源码解读之延迟加载
1. 目的 本文主要解读MyBatis 延迟加载实现原理 2. 延迟加载如何使用 Setting 参数配置 设置参数 描述 有效值 默认值 lazyLoadingEnabled 延迟加载的全局开关.当 ...
- MongoError: server instance in invalid state undefined 解决办法
MongoDB关键点集锦(更新中...) 2017-01-20 09:33:48[其它数据库]点击数:15作者:Real_Bird的博客来源: 网络 随机为您推荐的文章:MongDB索引的介绍及使用 ...
- Android 相关重难点知识整理
[原文] 集合 对 HashMap 进行排序: HashMap 本身无序,但其子类 LinkedHashMap 使用链表结构,实现了有序.通过 HashMap#entrySet() 方法可以将 Map ...
- scala学习手记9 - =和==
= 赋值运算 scala的赋值运算和java的有着很大的不同.如a=b这样的赋值运算,在Java中返回值是a的值,在scala中返回的则是Unit(Unit是值类型,全局只存在唯一的值,即(),通常U ...
- cors实现跨域(.net和jquery)
本文引用自:http://blog.csdn.net/xuwei_xuwei/article/details/29845865 客户端 一个jquery cors请求例子: $.ajax({ ...
- GDI+ 双缓冲字体模糊
只是记录自己的UI库,对其他估计没什么帮助 void CListCtrlUI::ReFillRect(HDC hdc){ if (!m_pImage) { Graphics gs(hdc); int ...
- MyBatis学习(3)
MyBatis-逆向工程 Mybatis工作原理 一个MapperStatement代表一个封装改查标签的详细信息. Configuration对象保存了所有配置文件的详细信息. 总结:把配置文件的信 ...
- jQuery EasyUI Datagrid VirtualScrollView视图简单分析
大家都知道EasyUI的Datagrid组件在加载大数据量时的优势并不是很明显,相对于其他一些框架,如果数据量达到几千,便会比较慢,特别是在IE下面.针对这种情况,我们首要做的是要相办法优化datag ...
- js 验证 -身份证等
js验证身份证: function isIdCard(idCard) { var num = idCard.toLowerCase().match(/\w/g); if (idCard.match(/ ...
- spring mvc: 静态资源/文件配置
静态文件不用再放web-info 下面了,放在webapp/ 下面就行了(静态文件放web-inf下你在jsp都无法引用~ 注意一下所有js.css包括报表文件~ 配置文件等等等~ 不要放在web ...