展会信息港展会大全

浅谈.net平台下深拷贝和浅拷贝
来源:互联网   发布日期:2016-01-26 10:54:44   浏览:1342次  

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

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

基本概念:

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

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

基本概念之参考代码:

代码如下:

class Program

{

static void Main(string[] args)

{

Student s1 = new Student("li", 23);

//浅拷贝

Student s2 = s1;

s2.Age = 27;

s1.ShowInfo();//li's age is 27

//深拷贝

int i = 12;

int j = i;

j = 22;

Console.WriteLine(i);//12

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 的值。

深浅拷贝的实现:

代码如下:

public object Clone()

{

return this.MemberwiseClone();

}

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

参考代码:

代码如下:

class Program

{

static void Main(string[] args)

{

ClassA ca = new ClassA();

ca.value = 88;

ClassA ca2 = new ClassA();

ca2 = (ClassA)ca.Clone();

ca2.value = 99;

Console.WriteLine(ca.value + "-----" + ca2.value);//88---99

ClassB cb = new ClassB();

cb.Member.value = 13;

ClassB cb2 = (ClassB)cb.Clone();

cb2.Member.value = 7;

Console.WriteLine(cb.Member.value.ToString() + "------" + cb2.Member.value.ToString());//浅拷贝:7---7深拷贝:13----7

Console.Read();

}

}

public class ClassA : ICloneable

{

public int value = 0;

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 = 3;

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 = 1;

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 = { 2, 3, 4, 5 };

int[] numbersCopy = new int[5];

numbers.CopyTo(numbersCopy, 0);

numbersCopy[2] = 0;

int[] numbers1 = { 2, 3, 4, 5 };

int[] numbersClone1 = (int[])numbers1.Clone();

numbersClone1[2] = 0;

Console.Write(numbers[2] + "---" + numbersCopy[2]);//4---0

Console.Write(numbers1[2] + "---" + numbersClone1[2]);//4--0

//数组的复制也就是引用传递,指向的是同一个地址

int[] numbers2 = { 2, 3, 4, 5 };

int[] numbers2Copy = numbers2;

numbers2Copy[2] = 0;

Console.Write(numbers2[2]);//0

Console.Write(numbers2Copy[2]);//0

Console.Read();

}

}

暂不做分析,认真领悟

赞助本站

人工智能实验室

相关热词: 深拷贝 浅拷贝 net

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港