Deep Copy VS Shallow Copy

来源:互联网 发布:win7x64精简优化版 编辑:程序博客网 时间:2024/05/16 10:47


首先我们应该了解下什么是


深拷贝与浅拷贝


 浅拷贝:只复制对象的基本类型,对象类型,仍属于原来的引用

 深拷贝:不仅复制对象的基本类,同时也复制原来对象中的对象

 

C#中有两种类型变量,一种是值类型变量,一种是引用类型便利那个,对于值类型便利那个,深拷贝和浅拷贝都是通过复制操作实现的,其效果是一样的,将对象中的值类型的字段拷贝到新的对象中。这个很容易理解。本文重点讨论引用类型变量的拷贝机制和实现。


C#中引用类型对象的Copy操作有两种


为是上面说到的俩种。


浅拷贝和深拷贝的区别:


浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用字段则指复制它的一个引用到目标对象

 

注意: string类型有点特殊,对于浅拷贝,按类值类型对象进行处理。

 

浅拷贝的实现


1 使用OjbectMemberwiseClone实现

MemberwiseClone:创建当前Object的浅拷贝副本

MemberwiseClone方法创建一个浅表副本,方式是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制,如果该字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一个对象。

示例代码:

public class Person    {        public int Age { get; set; }        public string Address { get; set; }        public Name Name { get; set; }        public object Clone()        {           return   this.MemberwiseClone();            }            }    public class Name    {        public Name(string frisName,string lastName)        {            FristName = frisName;            LastName = lastName;        }        public string FristName { get; set; }        public string LastName { get; set; }    }


复制操作与使用ObjectMemberwiseClone实现

 对于引用类型的变量,我们有种误解,认为复制操作就是一种浅拷贝,其实是有区别的。

 1浅拷贝对于引用类型对象中的值类型字段进行了逐位复制。赋值运算符只是把源对象的引用赋值给目的对象,两者引用同一个对象。

2浅拷贝后的对象的值类型字段更改不会反映到源对象,而赋值运算后的对象类型字段更改会反映到源对象。

 

==================================

 

深拷贝的实现

 

相对于浅拷贝是指依照源对象为原型,创建一个新对象,将当前对象的所有字段进行执行逐位复制并支持递归,不管是值类型还是引用类型,不管是静态字段还是非静态字段。

C#中,我们有


三种方式实现深拷贝


1实现ICloneable接口,自定义拷贝功能

ICloneable接口包含一个成员Clone,以用于支持除MemberwiseClone所提供的克隆之外的克隆。Clone既可以为深层副本实现,也可以作为浅表层副本实现,在深层副本中,所有的对象都是重复的,而在浅表层副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。结果克隆必须与原始实例具有相同的类型。


2序列化/反序列化实现

不知道你有没有注意到DataSet对象,对于他提供的两个方法:

 DataSet .Clone方法,复制DataSet的结构,包括所有DataTable架构,关系和约束,不复制任何数据。

DataSet。其架构与当前DataSet的架构相同,但是不包含任何数据DataSet。注意如果已经创建的子类,则副本也将属于相同的子类。

 

DataSet. Copy方法复制该DataSet的结构和数据(若不理解相关术语,参考上篇博客 点击

 新的DataSet,具有与该DataSet相同的结构(表架构,关系和约束)和数据,

 

 

这两个既不是深,也不是浅拷贝,但是如果结合起来就是我们的深拷贝了。

序列化是将对象或对象图形转换为线性字节序列,以存储或传输到另一个位置的过程。反序列化是接受存储的信息并利用它重新创建对象的过程。
通过 ISerializable 接口,类可以执行其自己的序列化行为。

 

3通过反射实现

 

通过序列化/反射序列方式我们比较流畅的实现深拷贝,但是涉及 I/O操作,托管环境,就很耗费资源了。

这里利用反射特性。不详细解释了(也不很明白)


原创粉丝点击