为什么要用到深拷贝呢?比如我们建了某个类Person,并且实例化出一个对象,然后,突然需要把这个对象复制一遍,并且复制出来的对象要跟之前的一模一样,来看下我们一般会怎么做,看代码

  

public class Person
{
  public string Name { get; set; }
}

class Program
{
  static void Main(string[] args)
    {
      Person sourceP = new Person() { Name = "大哥" };
      Person copyP = sourceP;
      copyP.Name = "大哥大"; // 拷贝对象改变Name值
      // 结果都是"大哥",因为实现的是浅拷贝,一个对象的改变都会影响到另一个对象
      Console.WriteLine("Person.Name: [SourceP: {0}] [CopyP:{1}]", sourceP.Name, copyP.Name);
      Console.Read();
    }
}

运行结果如图

可以看到虽然复制了一份sourceP对象,但是修改新对象copyP的Name属性时,居然把原来的sourceP对象的值也改了。这里的原理是因为“=”号,在对引用类型使用时,仅仅是新建一个新的引用变量,然后把引用地址复制给了新的引用变量而已,并没有复制真正的内容,这时候如果需要复制真正内容的话,就需要用到深拷贝的方式了。

几种常见的深拷贝方式

1、利用反射实现

public static T DeepCopyByReflection<T>(T obj)
{
  if (obj is string || obj.GetType().IsValueType)
  return obj;

  object retval = Activator.CreateInstance(obj.GetType());
  FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance);
  foreach(var field in fields)
  {
    try
    {
      field.SetValue(retval, DeepCopyByReflection(field.GetValue(obj)));
    }
    catch { }
  }

  return (T)retval;
}

2、利用二进制序列化和反序列化

public static T DeepCopyByBinary<T>(T obj)
{
  object retval;
  using (MemoryStream ms = new MemoryStream())
  {
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(ms, obj);
    ms.Seek(0, SeekOrigin.Begin);
    retval = bf.Deserialize(ms);
    ms.Close();
  }
  return (T)retval;
}

注意,使用二进制序列化和反序列化时,在需要序列化的类上要加上[Serializable]

[Serializable]
public class Person
{
  public string Name { get; set; }
}

3、利用xml序列化和反序列化

public static T DeepCopyByXml<T>(T obj)
{
  object retval;
  using (MemoryStream ms = new MemoryStream())
  {
    XmlSerializer xml=new XmlSerializer(typeof(T));
    xml.Serialize(ms, obj);
    ms.Seek(0, SeekOrigin.Begin);
    retval = xml.Deserialize(ms);
    ms.Close();
  }
  return (T)retval;
}

c#实现深拷贝的几种方法的更多相关文章

  1. JS实现深拷贝的几种方法

    引 如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力. 此篇文章中也会简单阐述到栈 ...

  2. 【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法

    1 借用JSON对象的parse和stringify function deepClone(obj){ let _obj = JSON.stringify(obj), objClone = JSON. ...

  3. 一步步分析Java深拷贝的两种方式-clone和序列化

    今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clon ...

  4. JS 中深拷贝的几种实现方法

    JS 中深拷贝的几种实现方法1.使用递归的方式实现深拷贝 //使用递归的方式实现数组.对象的深拷贝 function deepClone1(obj) { //判断拷贝的要进行深拷贝的是数组还是对象,是 ...

  5. 2种方法实现java对象的深拷贝

    2种方法实现java对象的深拷贝 2017年12月03日 22:23:07 iCoding91 阅读数 4420更多 分类专栏: java   版权声明:本文为博主原创文章,遵循CC 4.0 BY-S ...

  6. js对象的深拷贝及其的几种方法

    深拷贝和浅拷贝是javascript中一个比较复杂的问题,也是面试官最喜欢问的问题之一,通过这个为可以看出是否入门,深拷贝和浅拷贝也是初学者经常犯错一个点. 简单来说深拷贝是拷贝储存在栈中的对象,而浅 ...

  7. 用浅/深拷贝、和HTML5方法解决js对象的引用的问题

    先来看一个例子 例一: var a=[1,2,3]; var b=a; b.push(4); alert(b);//1,2,3,4 alert(a);//1,2,3,4 var a=[1,2,3]; ...

  8. JS 深拷贝和浅拷贝概念,以及实现深拷贝的三种方式

    一.理解堆栈,基本数据类型与引用数据类型 1.堆栈 栈(stack):系统自动分配的内存空间,内存会由系统自动释放,用来存放函数的参数值,局部变量的值等,特点是先进后出. 堆(heap):系统动态分配 ...

  9. JS 判断数据类型的三种方法

    说到数据类型,我们先理一下JavaScript中常见的几种数据类型: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Functi ...

随机推荐

  1. 最牛MongoDB灾难恢复(WiredTiger.wt文件损坏,Mongo无法启动)

    WiredTiger.wt文件是mongoDB的元数据文件,存储了其他数据库表的元数据信息.笔者最近遇到了WiredTiger.wt文件损坏的情况,MongoDB无法启动,数据库中的重要数据危在旦夕. ...

  2. 第七章 手动部署Fisco Bcos 区块链并完成新增群组,在原有群组中新增机构

    鉴于笔者以前各大博客教程都有很多人提问,早期建立一个技术交流群,里面技术体系可能比较杂,想了解相关区块链开发,技术提问,请加QQ群:538327407 目标 1.新增群组搭建完整联盟链 2.根据群组新 ...

  3. POJ 1966:Cable TV Network(最小点割集)***

    http://poj.org/problem?id=1966 题意:给出一个由n个点,m条边组成的无向图.求最少去掉多少点才能使得图中存在两点,它们之间不连通. 思路:将点i拆成a和b,连一条a-&g ...

  4. 玲珑OJ 1083:XJT Love Digits(离线处理+哈希)

    http://www.ifrog.cc/acm/problem/1083 题意:比较好懂.注意答案的x不包含ax本身,所以才输出-1. 思路:离线处理.根据x排序,然后每次更新Hash[]数组就好了. ...

  5. 走近Java之包装器类Integer

    前几天,有个同事问了我一个关于Integer类赋值的问题,很有意思,我们一起来看一下(如果有说的不正确的地方,欢迎大家指正). 如上图,同样是赋值,但是两次比较的结果完全不同.我们走近了解一下. 在I ...

  6. 牛逼了,教你用九种语言在JVM上输出HelloWorld

    我们在<深入分析Java的编译原理>中提到过,为了让Java语言具有良好的跨平台能力,Java独具匠心的提供了一种可以在所有平台上都能使用的一种中间代码——字节码(ByteCode). 有 ...

  7. mac环境下java项目无创建文件的权限

    1.问题: 先抛问题,由于刚刚换用mac环境,之前windows上开发的代码调试完毕,还未上线.之后上线部署之前,tl直连测试本地环境(mac)环境,功能无法使用,显示java.io.IOExcept ...

  8. acm 模板

    Index 分类细则 说起分类准则,我也是很头疼,毕竟对于很多算法,他并不是单调的,而是多方面的都挂得上钩.所以,从始至终,分类准则一直都是我很纠结的问题. 经过思量,首先分出比较主流的几类:Numb ...

  9. MTSC2019第五届移动互联网测试开发大会PPT下载

    关注公众号「软件测试大本营」后台回复「MTSC」或「测试开发大会」即可获取云盘下载地址及提取码. 注:PPT文件版权归相关撰写人所有,仅供学习交流,请勿用于任何商业用途,谢谢 前不久在北京举办了第五届 ...

  10. 描述符\get/set/delete,init/new/call,元类

    6.23 自我总结 1.描述符__get__,__set__,__delete__ 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了____get__(),__set__(),__d ...