|
一个克隆对象的C#基类
简介
虽然在现实世界中的克隆课题是有争议的, 在.NET世界使用它却足够安全, 难道不是吗?
为实现一个类你究竟有多少次要实现ICloneable接口, 而且每一次都写相同的代码,或为每个类写特定的代码。而且,当你的类加入一个新的字段时,往往会忘记更新这个新字段的克隆方法。如果我没说错的话,这种时候往往会带来恼人的bugs。
这是我的类得以存在的原因。 藉由反射机制的小小帮助,我建立了一个用缺省行为实现了ICloneable接口的抽象类。现在或许你正在问自己: 什么是缺省行为? 那么我很高兴你这样询问。 克隆的缺省行为,是采用以下的规则来克隆类中的每一个字段:
查看一下类中的每一个字段是否支持ICloneable接口
如果某字段不支持ICloneable接口,那么该字段将以常规方式处理。这意味着,如果该字段是一个值类型,那么该值被拷贝;如果该字段是一个引用类型,克隆的字段将指向同一个对象。
如果该字段支持ICloneable接口,我们将使用其本身的Clone方法对其进行克隆。
如果该字段支持IEnumerable接口,我们需要检查他是否支持IList 或 IDictionary 接口。如果支持,那么我们迭代该集件,并且查看集合的每一项是否支持ICloneable接口。
如何使用
让你的类支持Icloneable接口所要做的就是,将你的类继承自如下所述的BaseObject类:
public class MyClass : BaseObject
{
public string myStr ="test";
public int id;
}
public class MyContainer : BaseObject
{
public string name = "test2";
public MyClass[] myArray= new MyClass[5];
public class MyContainer()
{
for(int i=0 ; i<5 ; i++)
{
this.myArray[I] = new MyClass();
}
}
}
现在在Main方法中加入如下代码:
static void Main(string[] args)
{
MyContainer con1 = new MyContainer();
MyContainer con2 = (MyContainer)con1.Clone();
con2.myArray[0].id = 5;
}
当监测con2实例时,你将会看到MyClass实例的第一项已经变为5,而con1实例却没有改变。这样你将明白加入到类中的任意支持ICloneable接口的字段将被同样地克隆。而且,如果该字段支持IList 或 IDictionary 接口,克隆方法将侦测该字段,轮询所有项,并同样地试图对他们进行克隆。
实现的代码:
|