C#中有两种类型变量,一种是值类型变量,一种是引用类型变量。对于前者,copy是属于全盘复制;
而对于后者,一般的copy只是浅copy,相当于只传递一个引用指针一样。因此对于后者进行真正copy的时候,也是最费事的,具体的说,必须为其实现ICloneable接口中提供的Clone方法,示例代码如下:
public
class
Test
{
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);
}
}
{
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#中对于存放引用类型的数组,数组本身的引用类型和数组中元素的引用类型不能混为一谈,此时的数组仅相当于一个容器,所以对于容器本身和容器中存放的东西是要分别进行实例化的。呵呵困扰我很多天的问题贴上来做个备忘哈