首先介绍一下:
C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量。对于前者,copy是属于全盘复制;而对于后者,一般的copy只是浅copy,相当于只传递一个引用指针一样。因此 对于后者进行真正copy的时候,也是最费事的,具体的说,必须为其实现ICloneable接口中提供的Clone方法。
浅拷贝(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用.
深拷贝(深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.就是说完全是新对象产生的.
浅 拷贝和深拷贝之间的区别:浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象 中引用型字段的值他将反映在原是对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一 个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对 象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。
MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用 类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。深拷贝,即实现ICloneable接口.ICloneable可用于深拷贝 和浅拷贝。%Á÷ajØ7NKwww.pin5i.com6Ì~ÜK-H}c
这些都是概念,但是需要我们理解,下面介绍实例:


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.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 [] 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.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的用法,两者都不会改变其中的值,与上面我们的复制有很大的区别
因为数组里面是值类型,所以他们不存在引用,而
class class1
...{
public string aa = " aa " ;
}
class class4
...{
public static void Main()
...{
class1 aaa = new class1();
class1[] array3 = new class1[ 1 ];
class1[] array4 = new class1[ 1 ];
array3[ 0 ] = aaa;
// Array.Copy(array3, 0, array4, 0,1);
array3.CopyTo(array4, 0 );
// array4=(class1[])array3.Clone();
array3[ 0 ].aa = " bb " ;
Console.Write(array4[ 0 ].aa);
Console.Read();
}
}
结果是两者都改变了值,最后输出都是bb,那时因为两者都是浅拷贝,区别上面已经介绍了,所以
都没有实现深拷贝,以上如果分析有错误请大家指出,这只是我这么认为!
[文章出处]http://blog.youkuaiyun.com/xiaolei1982/archive/2008/04/02/2245480.aspx