在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力。所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的。

  

基本概念:

浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个对象。大部分的引用类型,实现的都是浅拷贝,引用类型对象之间的赋值,就是复制一个对象引用地址的副本,而指向的对象实例仍然是同一个。

深拷贝:指对象的子段被拷贝,同时字段引用的对象也进行了拷贝。深拷贝创建的是整个源对象的结构,拷贝对象和原对象相互独立,不共享任何实例数据,修改一个对象不会影响到另一个对象。值类型之间的赋值操作,执行的就是深拷贝。

基本概念之参考代码:

class Program
{
static void Main(string[] args)
{
Student s1 = new Student("li", ); //浅拷贝
Student s2 = s1;
s2.Age = ;
s1.ShowInfo();//li's age is 27 //深拷贝
int i = ;
int j = i;
j = ;
Console.WriteLine(i);// 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”的值。

注:上述实例中的“浅拷贝”和“深拷贝”其实都和浅拷贝、深拷贝没有关系(因为它们都没有实现Clone),仅仅是为了说明浅拷贝和深拷贝的效果。

深浅拷贝的实现:

public object Clone()
{
return this.MemberwiseClone();
}

MemberwiseClone:创建一个浅表副本。过程是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用对象。

参考代码:

class Program
{
static void Main(string[] args)
{
ClassA ca = new ClassA();
ca.value = ;
ClassA ca2 = new ClassA();
ca2 = (ClassA)ca.Clone();
ca2.value = ;
Console.WriteLine(ca.value + "-----" + ca2.value);//88---99 ClassB cb = new ClassB();
cb.Member.value = ; ClassB cb2 = (ClassB)cb.Clone();
cb2.Member.value = ;
Console.WriteLine(cb.Member.value.ToString() + "------" + cb2.Member.value.ToString());//浅拷贝:7---7 深拷贝:13----7 Console.Read();
}
} public class ClassA : ICloneable
{
public int value = ; 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 = ; 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 = ;
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 = { , , , };
int[] numbersCopy = new int[];
numbers.CopyTo(numbersCopy, );
numbersCopy[] = ; int[] numbers1 = { , , , };
int[] numbersClone1 = (int[])numbers1.Clone();
numbersClone1[] = ; Console.Write(numbers[] + "---" + numbersCopy[]);//4---0
Console.Write(numbers1[] + "---" + numbersClone1[]);//4--0 //数组的复制也就是引用传递,指向的是同一个地址
int[] numbers2 = { , , , };
int[] numbers2Copy = numbers2;
numbers2Copy[] = ; Console.Write(numbers2[]);//
Console.Write(numbers2Copy[]);// Console.Read();
}
}

暂不做分析,认真领悟。

引用:

浅拷贝和深拷贝

.net平台下深拷贝和浅拷贝的更多相关文章

  1. 浅谈.net平台下深拷贝和浅拷贝

    在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的 ...

  2. java对象的克隆以及深拷贝与浅拷贝

    一.为什么要使用克隆 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也 ...

  3. Objective-C中的深拷贝和浅拷贝

    在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...

  4. $.extend()的深拷贝和浅拷贝详细讲解

    版权声明:作者原创,转载请注明出处! 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 描述: 将两个或更多对象的内容合并到第一个对象 ...

  5. C++的深拷贝与浅拷贝

    对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面是一个类对象拷贝的简单例子. #i ...

  6. [C#进阶系列]专题一:深入解析深拷贝和浅拷贝

    一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...

  7. C++拷贝构造函数(深拷贝,浅拷贝)

    对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #i ...

  8. python 深拷贝与浅拷贝

    浅拷贝的方式有: lst=[1,2,3] (1)直接赋值: lst_cp = lst (2)for循环遍历生成:lst_cp= [i for i in lst] (3)copy模块下,copy.cop ...

  9. python 中 深拷贝和浅拷贝的理解

    在总结 python 对象和引用的时候,想到其实 对于python的深拷贝和浅拷贝也可以很好对其的进行理解. 在python中,对象的赋值的其实就是对象的引用.也就是说,当创建一个对象,然后赋给另外一 ...

随机推荐

  1. 完美洗牌&洗牌

    完美洗牌问题,给定一个数组a1,a2,a3,...an,b1,b2,b3..bn,把它最终设置为b1,a1,b2,a2,...bn,an这样的. O(n)的算法,O(n)的空间. 对于前n个数,映射为 ...

  2. 批量硬关联本地AD帐号与Office云端帐号

    世纪互联给的方案, 说只能一个一个做硬匹配, 把我吓尿了. 我整个简单的, 还能批量做. 1. 将本地域中所有用户的这两个属性导出. Get-ADUser -Filter * -SearchBase ...

  3. Spring3.1 Cache注解

    依赖jar包: <!-- redis --> <dependency> <groupId>org.springframework.data</groupId& ...

  4. replication set复制集

    replication set复制集  介绍 replicattion set 多台服务器维护相同的数据副本,提高服务器的可用性,总结下来有以下好处: 数据备份与恢复 读写分离 MongoDB 复制集 ...

  5. 块级&行内(内联)元素

    行内元素列表 <a>标签可定义锚 <abbr>表示一个缩写形式 <acronym>定义只取首字母缩写 <b>字体加粗 <bdo>可覆盖默认的 ...

  6. HDU 2089 数位dp入门

    开始学习数位dp...一道昨天看过代码思想的题今天打了近两个小时..最后还是看了别人的代码找bug...(丢丢) 传说院赛要取消 ? ... 这么菜不出去丢人也好吧~ #include<stdi ...

  7. Redis 笔记与总结3 list 类型

    redis 版本 [root@localhost ~]# redis-server --version Redis server v= sha=: malloc=jemalloc- bits= bui ...

  8. django 1.8 日志配置

    django 1.8 日志配置 以下为setings配置logging代码片段 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(_ ...

  9. python实践3:cursor() — 数据库连接操作

    python 操作数据库,要安装一个Python和数据库交互的包MySQL-python-1.2.2.win32-py2.5.exe,然后我们就可以使用MySQLdb这个包进行数据库操作了. 操作步骤 ...

  10. Nginx 常用全局变量 及Rewrite规则详解

    每次都很容易忘记Nginx的变量,下面列出来了一些常用 $remote_addr //获取客户端ip $binary_remote_addr //客户端ip(二进制) $remote_port //客 ...