• 原型模式 对象深浅复制


    对象的克隆:就是对象实例化的拷贝,在实际应用中我们其实就用到了对象拷贝,例如值类型的赋值操作,引用类型的相互赋值,值类型的装箱操作等,其实这些都属于对象的克隆操作。不是所有的对象实例都可以被克隆,它必须实现一个接口: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
    }
  • 相关阅读:
    Timer类的常见使用方法
    转:HTTP协议简介
    DS-5新加交叉编译工具
    C++的引用
    C++构造函数的几种使用方法
    Eclipse 快捷键
    eclipse Outline里图标的含义
    Linux 内存映射函数 mmap()函数详解
    Sockit 硬件接口编程——点亮一个LED
    更新Preloader与uboot
  • 原文地址:https://www.cnblogs.com/shineqiujuan/p/1704424.html
Copyright © 2020-2023  润新知