原型模式 对象深浅复制

对象的克隆:就是对象实例化的拷贝,在实际应用中我们其实就用到了对象拷贝,例如值类型的赋值操作,引用类型的相互赋值,值类型的装箱操作等,其实这些都属于对象的克隆操作。不是所有的对象实例都可以被克隆,它必须实现一个接口: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
}

 

 

posted @ 2010-04-04 22:57  chunchill  阅读(306)  评论(0编辑  收藏  举报