热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Object.MemberwiseClone(浅Clone、深Clone)

MemberwiseClone方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则

MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。 如果字段是值类型的,则对该字段执行逐位复制。 如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。

 

例如,考虑引用对象 A 和 B 的被称为 X 的对象。 对象 B 依次引用对象 C。 X 的浅表副本创建一个新对象 X2,该对象也引用对象 A 和 B。 相比而言,X 的深层副本创建一个新对象 X2,该对象引用新对象 A2 和 B2(分别为 A 和 B 的副本)。 B2 又引用新对象 C2,C2 是 C 的副本。 该示例阐释了浅层和深层复制操作之间的区别。

有很多方法可以实现深层复制操作,前提是浅表复制操作由 MemberwiseClone 方法执行但不符合您的需求。 这些要求包括:

  • 调用要复制的对象的类构造函数以创建含有从第一个对象中提出的属性值的第二个对象。 这假定对象的值完全由类构造函数定义。

  • 调用 MemberwiseClone 方法创建的对象的浅表副本,然后将指定新的对象,其值均相同,原始对象的任何属性或字段的值是引用类型。 该示例中的 DeepCopy 方法阐释了这种方法。

  • 序列化要深层复制的对象,然后将序列化的数据还原到另一个对象变量。

  • 使用带递归的反射执行的深层复制操作。

      1 using System;
      2 
      3 public class IdInfo
      4 {
      5     public int IdNumber;
      6 
      7     public IdInfo(int IdNumber)
      8     {
      9         this.IdNumber = IdNumber;
     10     }
     11 }
     12 
     13 public class Person 
     14 {
     15     public int Age;
     16     public string Name;
     17     public IdInfo IdInfo;
     18 
     19     public Person ShallowCopy()
     20     {
     21        return (Person)this.MemberwiseClone();
     22     }
     23 
     24     public Person DeepCopy()
     25     {
     26        Person other = (Person) this.MemberwiseClone(); 
     27        other.IdInfo = new IdInfo(this.IdInfo.IdNumber);
     28        return other;
     29     }
     30 }
     31 
     32 public class Example
     33 {
     34     public static void Main()
     35     {
     36         // Create an instance of Person and assign values to its fields.
     37         Person p1 = new Person();
     38         p1.Age = 42;
     39         p1.Name = "Sam";
     40         p1.IdInfo = new IdInfo(6565);
     41 
     42         // Perform a shallow copy of p1 and assign it to p2.
     43         Person p2 = (Person) p1.ShallowCopy();
     44 
     45         // Display values of p1, p2
     46         Console.WriteLine("Original values of p1 and p2:");
     47         Console.WriteLine("   p1 instance values: ");
     48         DisplayValues(p1);
     49         Console.WriteLine("   p2 instance values:");
     50         DisplayValues(p2);
     51 
     52         // Change the value of p1 properties and display the values of p1 and p2.
     53         p1.Age = 32;
     54         p1.Name = "Frank";
     55         p1.IdInfo.IdNumber = 7878;
     56         Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
     57         Console.WriteLine("   p1 instance values: ");
     58         DisplayValues(p1);
     59         Console.WriteLine("   p2 instance values:");
     60         DisplayValues(p2);
     61 
     62         // Make a deep copy of p1 and assign it to p3.
     63         Person p3 = p1.DeepCopy();
     64         // Change the members of the p1 class to new values to show the deep copy.
     65         p1.Name = "George";
     66         p1.Age = 39;
     67         p1.IdInfo.IdNumber = 8641;
     68         Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
     69         Console.WriteLine("   p1 instance values: ");
     70         DisplayValues(p1);
     71         Console.WriteLine("   p3 instance values:");
     72         DisplayValues(p3);
     73     }
     74 
     75     public static void DisplayValues(Person p)
     76     {
     77         Console.WriteLine("      Name: {0:s}, Age: {1:d}", p.Name, p.Age);
     78         Console.WriteLine("      Value: {0:d}", p.IdInfo.IdNumber);
     79     }
     80 }
     81 // The example displays the following output:
     82 //       Original values of p1 and p2:
     83 //          p1 instance values:
     84 //             Name: Sam, Age: 42
     85 //             Value: 6565
     86 //          p2 instance values:
     87 //             Name: Sam, Age: 42
     88 //             Value: 6565
     89 //       
     90 //       Values of p1 and p2 after changes to p1:
     91 //          p1 instance values:
     92 //             Name: Frank, Age: 32
     93 //             Value: 7878
     94 //          p2 instance values:
     95 //             Name: Sam, Age: 42
     96 //             Value: 7878
     97 //       
     98 //       Values of p1 and p3 after changes to p1:
     99 //          p1 instance values:
    100 //             Name: George, Age: 39
    101 //             Value: 8641
    102 //          p3 instance values:
    103 //             Name: Frank, Age: 32
    104 //             Value: 7878

转:https://www.cnblogs.com/hawk0450/archive/2012/03/14/2396028.html



推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 代理模式的详细介绍及应用场景
    代理模式是一种在软件开发中常用的设计模式,通过在客户端和目标对象之间增加一层中间层,让代理对象代替目标对象进行访问,从而简化系统的复杂性。代理模式可以根据不同的使用目的分为远程代理、虚拟代理、Copy-on-Write代理、保护代理、防火墙代理、智能引用代理和Cache代理等几种。本文将详细介绍代理模式的原理和应用场景。 ... [详细]
  • 手把手教你使用GraphPad Prism和Excel绘制回归分析结果的森林图
    本文介绍了使用GraphPad Prism和Excel绘制回归分析结果的森林图的方法。通过展示森林图,可以更加直观地将回归分析结果可视化。GraphPad Prism是一款专门为医学专业人士设计的绘图软件,同时也兼顾统计分析的功能,操作便捷,可以帮助科研人员轻松绘制出高质量的专业图形。文章以一篇发表在JACC杂志上的研究为例,利用其中的多因素回归分析结果来绘制森林图。通过本文的指导,读者可以学会如何使用GraphPad Prism和Excel绘制回归分析结果的森林图。 ... [详细]
author-avatar
finaokas_261
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有