原型模式 对象深浅复制
对象的克隆:就是对象实例化的拷贝,在实际应用中我们其实就用到了对象拷贝,例如值类型的赋值操作,引用类型的相互赋值,值类型的装箱操作等,其实这些都属于对象的克隆操作。不是所有的对象实例都可以被克隆,它必须实现一个接口:ICloneable接口。该接口的定义:
public interface ICloneable
{
object Clone();
}
对象的克隆可以分两种:深拷贝、浅拷贝。
浅拷贝:拷贝时值类型拷贝到新的实例,对于引用类型则只拷贝引用。
深拷贝:拷贝对象和源对象是完全不同的两个实体,只是这两个实体的内容一致而已,也就是说不但引用改变了,而且实体也被复制了一份。
浅复制(浅拷贝)Demo
class Program
{
static void Main(string[] args)
{
Student s1 = new Student("Jone", 23);
Student s2 = s1;//此处实际就是一个浅拷贝
s2.Age = 27;
s1.ShowInfo();
}
}
class Student
{
public string Name;
public int Age;
public Student(string name,int age)
{
Name = name;
Age = age;
}
public void ShowInfo()
{
Console.WriteLine("{0}'s age is {1}",Name,Age);
Console.Read();
}
}
值类型的赋值其实就是一种典型的深拷贝:
public void Main()
{
int i=100;
int j=i;
j=200;
Console.WriteLine(i.ToString());
}
//执行结果:100
在.NET类库中,System.Array就实现了ICloneable接口,通过反射可以看到其实现的代码为:
Public object Clone()
{
return base.MebmberwiseClone();
}
Clone方法通过调用基类System.Object的受保护方法MemberwiseClone实现Array类型的浅拷贝。因为,在.NET中,一切方法都继承与System.Object 类,所以开发人员可以通过调用MemberClone方法来实现自定义类型的浅拷贝。
自定义类型实现拷贝Demo:
实现浅拷贝:
代码
class Enrollment : ICloneable
{
public List<Student> students = new List<Student>();
public void ShowEnrollmentInfo()
{
Console.WriteLine("以下是所有登记学生的名单:");
foreach (Student item in students)
{
Console.WriteLine("{0}'s age is {1}",item.Name,item.Age);
}
Console.Read();
}
#region ICloneable 成员
public object Clone()
{
return base.MemberwiseClone();//浅拷贝
}
#endregion
}
在使用的时候改变拷贝对象的时候会改变源对象的值,因为浅拷贝用的是同一对象实例:
代码
static void Main(string[] args)
{
Enrollment sourceStudentsList = new Enrollment();
sourceStudentsList.students.Add(new Student("jone", 20));
sourceStudentsList.students.Add(new Student("tom", 21));
//实现对象的克隆,执行浅拷贝还是深拷贝
// 取决于Clone方法的实现
Enrollment cloneStudentsList = sourceStudentsList.Clone() as Enrollment;
cloneStudentsList.students[0].Name = "Jonery";
Console.WriteLine(sourceStudentsList.students[0].Name);
Console.Read();
}
如果要实现深拷贝只要更改Enrollment类:
代码
class Enrollment : ICloneable
{
public List<Student> students = new List<Student>();
public void ShowEnrollmentInfo()
{
Console.WriteLine("以下是所有登记学生的名单:");
foreach (Student item in students)
{
Console.WriteLine("{0}'s age is {1}",item.Name,item.Age);
}
Console.Read();
}
public Enrollment()
{ }
public Enrollment(List<Student> studentList)
{
foreach (Student item in studentList)
{
students.Add(item);
}
}
#region ICloneable 成员
public object Clone()
{
return new Enrollment(students);//浅拷贝
}
#endregion
}


浙公网安备 33010602011771号