C#中有两种类型变量,一种是值类型变量,一种是引用类型变量。对于前者,copy是属于全盘复制;
而对于后者,一般的copy只是浅copy,相当于只传递一个引用指针一样。因此对于后者进行真正copy的时候,也是最费事的,具体的说,必须为其实现ICloneable接口中提供的Clone方法,示例代码如下:
{
public class Person : ICloneable
{
public int ID;
public int age;
public void Show()
{
Console.WriteLine("ID:{0} 年龄:{1}",ID, age);
}
public object Clone()
{
Person newPerson = new Person();
newPerson.ID = this.ID;
newPerson.age = this.age;
return newPerson;
}
}
public static void ShowPersons(Person[] persons)
{
for (int i=0; i<persons.GetLength(0); i++)
{
persons[i].Show();
}
}
static void Main(string[] argv)
{
Random rnd = new Random(unchecked((int)DateTime.Now.Ticks));
Person[] persons = new Person[4];
for (int i=0;i<persons.GetLength(0);i++)
{
persons[i] = new Person();
persons[i].ID = rnd.Next()%10;
persons[i].age = rnd.Next()%50;
}
//打印原始数组
Console.WriteLine("打印原始数组");
ShowPersons(persons);
//深拷贝
Person[] personsCopied = new Person[4];
for (int i=0;i<personsCopied.GetLength(0);i++)
{
personsCopied[i] = (Person)persons[i].Clone();
}
//persons.CopyTo(personsCopied, 0);
Console.WriteLine("深拷贝的数组");
ShowPersons(personsCopied);
// //浅拷贝
// Person[] personsCloned = (Person[])persons.Clone();
// Console.WriteLine("浅拷贝的数组");
// ShowPersons(personsCloned);
//对原数组做修改
persons[2].ID += 10;
Console.WriteLine("打印修改后的原始数组");
ShowPersons(persons);
Console.WriteLine("深拷贝的数组应该不改变");
ShowPersons(personsCopied);
// Console.WriteLine("浅拷贝的数组应该改变");
// ShowPersons(personsCloned);
}
}
某次的运行结果:
对于上例,在进行深拷贝时,必须先为对象数组new新的空间,而数组中的对象成员则由实现了接口的相应方法分配新的空间,由深拷贝出来的新对象数组不会因为原数组的改变而改变,相反,对于注释行中仅作了浅表复制的personsCloned而言则会受原数组的影响。
另外注意 persons.CopyTo(personsCopied, 0); 这一句并不是对personsCopied进行深表复制,数组直接拷贝是拷贝的指向同一个对象的引用,因为在C#中对于存放引用类型的数组,数组本身的引用类型和数组中元素的引用类型不能混为一谈,此时的数组仅相当于一个容器,所以对于容器本身和容器中存放的东西是要分别进行实例化的。呵呵困扰我很多天的问题贴上来做个备忘哈