中易网

求助深拷贝和浅拷贝的问题

答案:1  悬赏:70  
解决时间 2021-02-04 06:43
求助深拷贝和浅拷贝的问题
最佳答案
浅拷贝就比如像引用类型,而深拷贝就比如值类型。
浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉。
深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。

C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量。对于前者,copy是属于全盘复制;而对于后者,一般的copy只是浅copy,相当于只传递一个引用指针一样。因此 对于后者进行真正copy的时候,也是最费事的,具体的说,必须为其实现ICloneable接口中提供的Clone方法。

浅拷贝(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用.
深拷贝(深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.就是说完全是新对象产生的.

浅 拷贝和深拷贝之间的区别:浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象 中引用型字段的值他将反映在原是对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一 个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对 象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。

MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用 类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。深拷贝,即实现ICloneable接口.ICloneable可用于深拷贝 和浅拷贝。
这些都是概念,但是需要我们理解,下面介绍实例:

using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsApplication1
{
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;
}
}

public class class4
{
public static void Main()
{
ClassB sb = new ClassB();
sb.Member.Value = 15;

ClassB nb = (ClassB)sb.Clone();
nb.Member.Value = 6;
Console.Write(sb.Member.Value.ToString() + "---" + nb.Member.Value.ToString());
ClassA nnb = new ClassA();
nnb.Value = 111;
ClassA bbn = new ClassA();
bbn = (ClassA)nnb.Clone();
bbn.Value = 222;
Console.Write(bbn.Value);
Console.Read();

}
}
}

其中.MemberwiseClone()在上面已经介绍过了,通过实例可以清楚看到浅拷贝与深拷贝的区别
再来个:

using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsApplication1
{
class Program
{
public class Sex
{
private string _PSex;
public string PSex
{
set
{
_PSex = value;
}
get
{
return _PSex;
}
}

}

public class Person : ICloneable
{

private Sex _pSex = new Sex();
public int aa = 1213;

public string pSex
{
set
{
_pSex.PSex = value;
}
get
{
return _pSex.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;
}

}

static void Main(string[] args)
{
Console.WriteLine("原对象:");
Person p = new Person();
p.PName = "JackLee";
p.pSex = "男";

p.ShowPersonInfo();

//浅拷贝
Person copy = (Person)p.Clone();
//深拷贝
Person dcopy = (Person)p.DeepClone();

Console.WriteLine("修改后的原对象:");
p.PName = "JackZhao";
p.pSex = "女";
p.aa = 1111;
p.ShowPersonInfo();

Console.WriteLine("修改后的浅拷贝对象:");
copy.ShowPersonInfo();
Console.WriteLine("修改后的深拷贝对象:");
dcopy.ShowPersonInfo();

Console.WriteLine("直接拷贝对象:");
Person PP = p;
PP.ShowPersonInfo();

Console.ReadLine();

}

}
}

接下来介绍一下数组的拷贝:
首先数组的直接拷贝也就是复制,不用多说看例子:

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

int [] numbersCopy = numbers;

numbersCopy[2] = 0;

Console.Write(numbers[2]);

Console.Write(numbersCopy[2]);

结果就是
0
0
道理很简单,数组的复制也就是引用传递,指向的是同一个地址,这不是我们介绍的重点
接下来
看一下概念
数组是引用类型,所以将一个数组变量赋予另一个数组变量,就会得到两个指向同一数组的变量。而复制数组,会使数组实现ICloneable接口。这个接口定义的Clone()方法会创建数组的浅副本。
如果数组的元素是值类型,就会复制所有的值,如果数组包含引用类型,则不复制元素,而只复制引用,

除了使用Clone()方法之外,还可以使用Array.Copy()方法创建浅副本。但Clone()方法和Copy()方法有一个重要区别:Clone()方法会创建一个新数组,而Copy()方法只是传送了阶数相同、有足够元素空间的已有数组。
提示:
如果需要包含引用类型的数组的深副本,就必须迭代数组,创建新对象。
看一下例子:

using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsApplication1
{
class Class2
{
public static void Main()
{
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]);

Console.Read();

}
}
}

我这里介绍的主要是数组的clone和copyto的用法,两者都不会改变其中的值,与上面我们的复制有很大的区别
我要举报
如以上问答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
关于 Maya 的 Fcheck 问题
请给我独角兽高达两种模式拼装图(中文)
为什么没钱得人穷大方还不知道节省 有钱的人
青春集结号教导员结婚时的插曲什么
安之阳化妆名品店在哪里啊,我有事要去这个地
为什么体检结果是“肝功能异常,定期复查”
大专毕业 化学仪器分析的就业前景怎样
1969年旧历正月二十六生人的运程
下庄地址在哪,我要去那里办事
55岁已经在领养老金,医疗保险还在买,但因有
苹果5下载乐动力爬楼梯
木墙裙墙面的构造做法是什么
梦见自己给别人写证明
鑫皇世足浴地址有知道的么?有点事想过去
企业买社保(工作的时候)和个人(个体户)买
推荐资讯
联想一体机B540能换显卡吗
武威市公安局凉州分局金羊派出所在什么地方啊
宏源电子(沈阳中路)地址有知道的么?有点事想
常州市武进区横林生达五金厂在哪里啊,我有事
上上ktv(昌顺广场店)怎么去啊,我要去那办事
EM菌和活力99用在农业上那种更好一些。主要用
北京可以开车上山看夕阳的山,最近的,急求!
怎么查询别人微信聊天记录,电脑怎么查询
佰诚汽车城市汽车展厅在什么地方啊,我要过去
清流县升隆印制厂这个地址在什么地方,我要处
为什么说美术教学目的是整个中学美术教学工作
龙万地址在哪,我要去那里办事
手机登qq时,显示手机磁盘不足,清理后重新登
刺客的套装怎么选啊?