在有些时候,我们需要从数据库读取数据填充对象或从硬盘读取文件填充对象,但是这样做相对耗时。这时候我们就想到了对象的拷贝。本文即以实例形式解析了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(); //对引用类型实施浅复制
  }
}

View Code

2.测试拷贝后的效果

①打印出原先对象  拷贝前值类型和引用类型成员的值 
②对原先对象拷贝,打印出复制对象值类型和引用类型成员的值 
③改变原先对象的值,再次打印原先对象的值类型和引用类型成员的值 
④再次打印复制对象值类型和引用类型成员的值

static void Main(string[] args)
{Room room1 = new Room(60);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 = 80;Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);Console.ReadKey();
}

View Code

运行结果如下:

分析:

浅拷贝关键点是对引用类型拷贝的是对象引用,这个引用指向托管堆上的对象实例。改变原对应引用类型的值,会影响到复制对象。

二、深拷贝

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 = 0;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 = 0;return (bf.Deserialize(ms));}
}

View Code

5.测试拷贝后的效果

static void Main(string[] args){Room room1 = new Room(60);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 = 80;Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);Console.ReadKey();}

View Code

结果:
分析:
深拷贝后,两个对象的引用成员已经分离,改变原先对象引用类型成员的值
并不会对复制对象的引用类型成员值造成影响。

转载于:https://www.cnblogs.com/peterYong/p/6556628.html

C# 浅拷贝与深拷贝(复制)相关推荐

  1. python如何复制一个变量_Python中变量、赋值、浅拷贝、深拷贝

    在理解浅拷贝和深拷贝之前,首先要理解学习一下变量在Python中是怎样存储的: 变量的类型是分值引用与地址引用两种. python的一切变量都是对象,变量的存储,采用了地址引用的方式,存储的只是一个变 ...

  2. python函数方法里面用浅复制深复制_图解 Python 浅拷贝与深拷贝

    Python 中的赋值语句不会创建对象的拷贝,仅仅只是将名称绑定至一个对象.对于不可变对象,通常没什么差别,但是处理可变对象或可变对象的集合时,你可能需要创建这些对象的 "真实拷贝" ...

  3. java数组深拷贝和浅拷贝_java List复制:浅拷贝与深拷贝

    Java的拷贝可以分为三种:浅拷贝(Shallow Copy).深拷贝(Deep Copy).延迟拷贝(Lazy Copy). 在java中除了基本数据类型之外(int,long,short等),还存 ...

  4. 【Python成长之路】快速理解复制、浅拷贝、深拷贝

    哈喽大家好,我是鹏哥. 今天想聊聊的主题是 -- 浅拷贝/深拷贝. ~~~上课铃~~~ 赤伶HITA - 赤伶 1 写在前面 浅拷贝.深拷贝的知识点,在python笔试和面试的过程中,经常被作为考题来 ...

  5. 复制、浅拷贝、深拷贝

    目录 一.概念 1.复制(赋值) 2.浅拷贝 3.深拷贝 二.示例 一.概念 1.复制(赋值) 产生原对象的引用,不开辟新的内存空间,使用指针指向原对象,跟原对象完全一样.当对原对象进行操作时,复制对 ...

  6. C++深拷贝和浅拷贝(深复制和浅复制)完全攻略

    C++深拷贝和浅拷贝(深复制和浅复制)完全攻略 对于基本类型的数据以及简单的对象,它们之间的拷贝非常简单,就是按位复制内存.例如: class Base{public:Base(): m_a(0), ...

  7. 【JavaScript】23_浅拷贝和深拷贝 + 对象的复制 + 数组的常用方法

    7.浅拷贝和深拷贝 浅拷贝(shallow copy) 通常对对象的拷贝都是浅拷贝 浅拷贝顾名思义,只对对象的浅层进行复制(只复制一层) 如果对象中存储的数据是原始值,那么拷贝的深浅是不重要 浅拷贝只 ...

  8. Python的复制、浅拷贝、深拷贝区别和代码说明

    Python赋值 总结 一.概念解读 赋值:旧瓶装旧酒 浅拷贝:新瓶装旧酒 深拷贝:新瓶装新酒 二.实例测试 测试方法 赋值 浅拷贝 深拷贝 附录:全代码 赋值.浅拷贝.深拷贝 总结 赋值: 新建一个 ...

  9. NumPy复制数组之浅拷贝和深拷贝(注意,直接用等号不是复制,且切片会改变原数组!!!)ndarray.copy() ndarray.view()(view()只是改变shape形状,数据还是同一个)

    引用文章:NumPy之浅拷贝和深拷贝

最新文章

  1. 解决Visual Studio For Mac Restore失败的问题
  2. oracle emctl
  3. c#+ArcGIS Engine-获取矢量图层的空间参考
  4. 2_6 CompositeMode.cpp 组合模式
  5. b g opencv读入的图片 r_OpenCV提取显示一张图片(或者视频)的R,G,B颜色分量
  6. linux应用程序安装PPT免费序,linux下应用程序安装的总结
  7. linux mysql select_MySQL-Select语句高级应用
  8. python求解三元一次方程_北师大版八上数学5.2 求解二元一次方程组 知识点微课精讲...
  9. 子类实现父类接口时注解为啥报错_Java中的注解使用:全面性的总结一下
  10. 公司决策层时刻想着:怎样开展业务,怎样防止公司完蛋
  11. Docker 安装 zookeeper
  12. Activity设置竖屏显示
  13. 【2019年05月10日】指数估值排名
  14. Excel--认识Excel
  15. 同账号不同服务器幻化T2,魔兽世界TBC怀旧服预热采访—不会开放幻化,直升58每个账号只有一次机会...
  16. 在godaddy使用支付宝
  17. Unity3D中实现帧同步 (一):对抗延迟
  18. drozer安装之夜深模拟器
  19. 格雷希尔快速连接器GripSeal 密封性测试密封堵头 G15Pro系列使用说明
  20. Leetcode动态规划专题(共38道)

热门文章

  1. java 随机生成图_java – 如何生成随机图?
  2. 腾讯校园招聘笔试 2019-8-17 第五题
  3. C#基础7:类的定义
  4. bzoj 4131: 并行博弈(博弈)
  5. bzoj 1131: [POI2008]Sta(DPS)
  6. [Python] 生成迭代器 iter() 函数
  7. python深度学习库keras——网络建模全解
  8. Eclipse 导入外部jar包
  9. AD打板过程简介(搭配某份教程实现)
  10. 富文本编辑器 CKeditor 配置使用 (带附件)