1.使用受保护的方法System.Object.MemberwiseClone()进行浅度复制。
方法如下:
假定有引用类型的字段,而不是值类型的字段(例如,对象):
下面的代码使用这个类来说明这一点:
Cloner mySource=new Cloner(5);
Cloner myTarget=(Cloner)mySource.GetCopy();
Console.WriteLine("myTarget.MyContent.Val={0}",myTarget.MyContent.Val);
mySource.MyContent.Val=2;
Console.WriteLine("myTarget.MyContent.Val={0}".myTarget.MyContent.Val);
第4行把一个值赋给MySource.MyContent.Val,源对象中公共域MyContent的公共域Val也改变了myTarget.MyContent.Val的值。这是因为mySource.MyContent引用了与myTarget.My.Content相同的对象实例。
上述代码的结果如下:
myTarget.MyContent.Val=5;
myTarget.MyContent.Val=2;
为了说明这个过程,需要执行深度复制。修改上面的GetCopy()方法就可以进行深度复制,但最好使用.Net FrameWork的标准方式。为此,实现ICloneable接口,该接口有一个方法Clone(),这个方法不带参数,返回一个对象类型,其签名和上面使用的GetCopy()方法相同。
修改上面使用的类,可以使用下面的深度复制代码:
public class Content
{
public int Val;
}
public class Cloner:ICloneable
{
public Content MyContent=new Content();
public Cloner(int newVal)
{
MyContent.Val=newVal;
}
public object Clone()
{
Cloner clonedCloner=new Cloner(MyContent.Val)
return clonedCloner();
}
}其中使用包含在源Cloner对象(MyContent)中的Content对象的Val字段,创建一个新Cloner对象。这个字段是一个值类型,所以不需要深度复制。
使用与上面类似的代码测试浅度复制,但使用Clone()而不是GetCopy(),得到如下结果:
myTarget.MyContent.Val=5
myTarget.MyContent.Val=5
这次包含的对象是独立的。
注意有时在比较复杂的对象系统中,调用Clone()是一个递归过程。例如,如果Cloner类的MyContent域也需要深度复制,就要使用下面的代码:
方法如下:
public class Cloner
{
public int Val;
public Cloner(int newVal)
{
Val=newVal;
}
public object GetCopy()
{
return MemberwiseClone();
}
}
{
public int Val;
public Cloner(int newVal)
{
Val=newVal;
}
public object GetCopy()
{
return MemberwiseClone();
}
}
假定有引用类型的字段,而不是值类型的字段(例如,对象):
public class Content
{
public int Val;
}
public class Cloner
{
public Content MyContent=new Content();
public Cloner(int newVal)
{
MyContent.Val=newVal;
}
public object GetCopy()
{
return MemberwiseClone();
}
}
此时,通过GetCopy()得到的浅度复制有一个字段,它引用的对象与源对象相同。{
public int Val;
}
public class Cloner
{
public Content MyContent=new Content();
public Cloner(int newVal)
{
MyContent.Val=newVal;
}
public object GetCopy()
{
return MemberwiseClone();
}
}
下面的代码使用这个类来说明这一点:
Cloner mySource=new Cloner(5);
Cloner myTarget=(Cloner)mySource.GetCopy();
Console.WriteLine("myTarget.MyContent.Val={0}",myTarget.MyContent.Val);
mySource.MyContent.Val=2;
Console.WriteLine("myTarget.MyContent.Val={0}".myTarget.MyContent.Val);
第4行把一个值赋给MySource.MyContent.Val,源对象中公共域MyContent的公共域Val也改变了myTarget.MyContent.Val的值。这是因为mySource.MyContent引用了与myTarget.My.Content相同的对象实例。
上述代码的结果如下:
myTarget.MyContent.Val=5;
myTarget.MyContent.Val=2;
为了说明这个过程,需要执行深度复制。修改上面的GetCopy()方法就可以进行深度复制,但最好使用.Net FrameWork的标准方式。为此,实现ICloneable接口,该接口有一个方法Clone(),这个方法不带参数,返回一个对象类型,其签名和上面使用的GetCopy()方法相同。
修改上面使用的类,可以使用下面的深度复制代码:
public class Content
{
public int Val;
}
public class Cloner:ICloneable
{
public Content MyContent=new Content();
public Cloner(int newVal)
{
MyContent.Val=newVal;
}
public object Clone()
{
Cloner clonedCloner=new Cloner(MyContent.Val)
return clonedCloner();
}
}
使用与上面类似的代码测试浅度复制,但使用Clone()而不是GetCopy(),得到如下结果:
myTarget.MyContent.Val=5
myTarget.MyContent.Val=5
这次包含的对象是独立的。
注意有时在比较复杂的对象系统中,调用Clone()是一个递归过程。例如,如果Cloner类的MyContent域也需要深度复制,就要使用下面的代码:
public class Cloner:ICloneable
{
public Content MyContent=new Content();
.
public object Clone()
{
Cloner clonedCloner=new Cloner();
clonedCloner.MyContent=MyContent.Clone();
return clonedCloner;
}
}
{
public Content MyContent=new Content();
.
public object Clone()
{
Cloner clonedCloner=new Cloner();
clonedCloner.MyContent=MyContent.Clone();
return clonedCloner;
}
}
这里调用了默认的构造函数,简化了创建一个新Cloner对象的方法。为了使这段代码能正常工作,还需要在Content类上实现ICloneable接口。
//实现Clone()方法可以实现深层复制
class test:ICloneable
{
public int a;
ICloneable 成员
}
class Program
{
static void Main(string[] args)
{
test t1 = new test();
t1.a = 4;
test t2=(test)t1.Clone();
t2.a = 8;
Console.WriteLine(t1.a);
}
}
//IClonable实现深度拷贝,举个例子
public class TDir : IClonable
{
private string[] _dirs;
private string[] _files;
public TDir()
{
_dirs = null;
_files = null;
}
public object Clone() // deep copy
{
TDir copy = new TDir();
if (_dirs != null)
{
ArrayList list = new ArrayList(_dirs.Length);
foreach (string i in _dirs)
list.Add(i);
copy._dirs = (string[])list.ToArray(typeof(string));
}
if (_files != null)
{
ArrayList list = new ArrayList(_files.Length);
foreach (string i in _files)
list.Add(i);
copy._files = (string[])list.ToArray(typeof(string));
}
return copy;
}
}
class test:ICloneable
{
public int a;
ICloneable 成员
}
class Program
{
static void Main(string[] args)
{
test t1 = new test();
t1.a = 4;
test t2=(test)t1.Clone();
t2.a = 8;
Console.WriteLine(t1.a);
}
}
//IClonable实现深度拷贝,举个例子
public class TDir : IClonable
{
private string[] _dirs;
private string[] _files;
public TDir()
{
_dirs = null;
_files = null;
}
public object Clone() // deep copy
{
TDir copy = new TDir();
if (_dirs != null)
{
ArrayList list = new ArrayList(_dirs.Length);
foreach (string i in _dirs)
list.Add(i);
copy._dirs = (string[])list.ToArray(typeof(string));
}
if (_files != null)
{
ArrayList list = new ArrayList(_files.Length);
foreach (string i in _files)
list.Add(i);
copy._files = (string[])list.ToArray(typeof(string));
}
return copy;
}
}
通用的克隆方法:
/// <summary>
/// 克隆
/// </summary>
/// <returns></returns>
public object Clone()
{
AwbBasic tObject = new AwbBasic();
PropertyInfo[] pTar = this.GetType().GetProperties();
PropertyInfo[] pSour = this.GetType().GetProperties();
foreach (PropertyInfo s in pSour)
{
foreach (PropertyInfo t in pTar)
{
if (s.Name == t.Name)
{
t.SetValue(tObject, s.GetValue(this, null), null);
}
}
}
return tObject;
}