C# 对象的拷贝
在程序设计中,我们有时希望得到现有一个对象的拷贝。
拷贝有两种:
(1)浅拷贝(也称浅表复制);(2)深拷贝(也称深度复制)
1.浅拷贝
表示将所有非引用数据类型从一个对象复制到另一个对象;如果原有对象包含对像引用,则复制对角引用(即是指当对象的字段值被拷贝时,字段的引用对象不会被拷贝)。形成拷贝后的对象与原对象会引用同一个值。
值的改变:修改副本中的对象引用时,原始列表也将更改,但当修改非引用项时,原始项保持不变。
如果希望自己的类型实现浅拷贝;可以像下面这样在方法中调用System.Object的受保护方法MemberwiseClone即可:
public Object Clone()
{
return this.MemberwiseClone();
}
实例1:
using System;
namespace ConsoleApplication6
{
class ptest:ICloneable
{
private int _weight;
private int _height;
public int[] v = { 1, 2, 3 };
public void Display()
{
foreach (int i in v)
Console.Write(i + ", ");
Console.WriteLine();
}
public int Weight
{
get
{ return _weight; }
set
{ _weight = value; }
}
public int Height
{
get
{ return _height; }
set
{ _height = value; }
}
public object Clone()
{
return this.MemberwiseClone();
}
}
class test
{
public static void Main()
{
ptest pa = new ptest();
pa.Height = 10;
pa.Weight = 20;
ptest pb = (ptest)pa.Clone(); //实现浅拷贝
Console.WriteLine(pb.Weight.ToString());
Console.WriteLine(pb.Height.ToString());
pa.Display();
pb.Display();
pb.Height = 40;
pa.v[0] = 40;
Console.WriteLine(pa.Height.ToString());
Console.WriteLine(pb.Height.ToString());
pa.Display();
pb.Display();
}
}
}
输出:
第一行: 20
第二行: 10
第三行: 1,2,3
第四行: 1,2,3
第五行: 10
第六行: 40
第七行: 40,2,3
第八行: 40,2,3
代码说明: 第一行至第四行说明:实现了已实例化对象pa的浅拷贝对象pb,故pb拥有与pa一样的值,且指向同一个对象ptest
第五行至第六行说明:浅拷贝对于修改非引用项(类型)时,原始项保持不变。故当改变pb.Height=40;后pa.Height仍为原来的值10;
第七行至第八行说明:浅拷贝对于修改的对象引用项(类型)时,原始列表也将更改。故当改变引用类型 int [] v 的v[0]=40;后两个对象的int []V的值都会改变.
2.深拷贝:是一种对对象实例中的引用对象也进行了拷贝的一种形式;如一个对象中有一个指向字符串的字段,并且我们对这个对象进行了深拷贝的话;将创建一个新的对象和一个新字符串,新对象将引用新的字符串字段。而且当我们对一个对象进行深拷贝后,两个对象将不会共享任何东西,改变任何一个对象对另一个对象不会产生任何影响。
ex:
using System;
class DeepCopy : ICloneable
{
public int[] v = {1,2,3};
// 默认构造函数
public DeepCopy()
{
}
// 供Clone方法调用的私有构造函数
private DeepCopy(int[] v)
{
this.v = (int[])v.Clone();
}
public Object Clone()
{
// 构造一个新的DeepCopy对象,构造参数为
// 原有对象中使用的 v
return new DeepCopy(this.v);
}
public void Display()
{
foreach(int i in v)
Console.Write( i + ", ");
Console.WriteLine();
}
}
class Client
{
public static void Main()
{
DeepCopy dc1 = new DeepCopy();
DeepCopy dc2 = (DeepCopy)dc1.Clone();
dc1.v[0] = 9;
dc1.Display();
dc2.Display();
}
}
这次在克隆的时候,不但克隆对象本身,连里面的数组字段一并克隆。因此,最终打印出来的dc1与dc2不同
输出:
9,2,3
1,2,3 //当我们对一个对象进行深拷贝后,两个对象将不会共享任何东西,改变任何一个对象对另一个对象不会产生任何影响。