zoukankan      html  css  js  c++  java
  • 浅谈浅拷贝与深拷贝

    浅拷贝与深拷贝
    再讲之前我们来解释下拷贝,顾名思义就是复制的意思。和物理上的拷贝不一样,在面向对象语言中拷贝涉及到类的继承、接口的实现等等。下面我们来讨论下浅拷贝与深拷贝的一些作用于区别。
    拷贝:一定要有一个新对象的出现,并且这两个对象一定要相同。
    下面是浅拷贝的一个例子:

     1 class Person{
     2 public string name;
     3 public int age;
     4 public char gender;
     5 Random r;
     6 public Person(string name,int age,char gender){
     7 this.name=name;
     8 this.age=age;
     9 this.gender=r.Next(2)==1?'':'';
    10 }
    11 }
    12 Person p1=new Person("张三",18,'');
    13 //浅拷贝方法1:直接赋值拷贝创建对象
    14 Person p2=new Person(p1.name,p1.age,p1.gender);
    15 //浅拷贝方法2:使用类的初始化器创建对象
    16 Person p3=new Person(){name=p1.name,age=p1.age,gender=p1.gender};

    但是这种两种拷贝方法却又一个缺陷,就是当内部变量赋值出现不可预测的因素时(Person类中的性别就是不可控因素),不能保证拷贝后的对象与之前的对象一样。所有我们提出了一个新的解决方案如下:
    思路:使用object类提供的一个受保护的方法来实现浅拷贝
    ①在对象中添加一个方法。
    ②该方法的返回值就是该类类型。
    ③return (该类类型)this.MemberwiseClone();
    代码如下:

     1 class Person{
     2 public string name;
     3 public int age;
     4 public char gender;
     5 public Person(string name,int age,char gender){
     6 this.name=name;
     7 this.age=age;
     8 this.gender=gender;
     9 }
    10 public Person Clone(){
    11 return (Person)this.MemberwiseClone();
    12 }
    13 }
    14 Person p1=new Person("张三",18,'');
    15 Person p2=p1.Clone();

    浅拷贝就不考虑对象中的引用类型成员,只是将对象中的内容全部拷贝一份,对于引用类型就是拷贝其存储的值,即地址。

    而深拷贝就是把对象的所有成员都拷贝一份,包括引用类型成员。但考虑到类中的引用类型有可能有很多或者以后会添加新的引用类型。我这里直接介绍一种最直接的方法。
    思路:通过对对象的序列化和反序列化来拷贝对象

     1 class Person{
     2 public string name;
     3 public int age;
     4 public char gender;
     5 public Car MyCar;
     6 public Person(string name,int age,char gender,string carName){
     7 this.name=name;
     8 this.age=age;
     9 this.gender=gender;
    10 MyCar=new Car();
    11 MyCar.name=carName;
    12 }
    13 public Person Clone(){
    14 return (Person)this.MemberwiseClone();
    15 }
    16 }
    17 class Car{
    18 public string name;
    19 }
    20 //序列化对象
    21 Person p1 = new Person("张三", 18, '');
    22 //创建二进制流对象
    23 BinaryFormatter bf = new BinaryFormatter();
    24 using (FileStream fs = new FileStream(@"E:1.dat", FileMode.Create, FileAccess.Write)) {
    25 bf.Serialize(fs, p1);
    26 }
    27 //反序列化dat文件
    28 //创建二进制流对象
    29 BinaryFormatter bf1 = new BinaryFormatter();
    30 //创建一个Persond对象来接收反序列化读的对象
    31 Person p2;
    32 using (FileStream fs1 = new FileStream(@"E:1.dat", FileMode.Open, FileAccess.Read)) {
    33 p2 = (Person)bf1.Deserialize(fs1);
    34 }
    QQ群:150417854
  • 相关阅读:
    面试6 在c#中如何声明一个类不能被继承
    面试5 如何理解静态变量,局部变量,全局变量
    面试4 你在什么情况下会用到虚方法?它与接口有什么不同
    面试3 不用系统自带的方法将字符串类型123456转换为值类型
    面试2 递归的算法求1,1,2,3,5,8.......的第30位数是多少,然后求这些数的和.
    面试1 SQL SERVER 查询第20行到30之间的数据
    ubuntu安装nginx
    ubuntu上使用ufw配置管理防火墙
    ubuntu上安装docker
    ubuntu上使用vim编辑文本内容
  • 原文地址:https://www.cnblogs.com/rampb/p/3384213.html
Copyright © 2011-2022 走看看