c#实现深拷贝的几种方法
为什么要用到深拷贝呢?比如我们建了某个类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#实现深拷贝的几种方法的更多相关文章
- JS实现深拷贝的几种方法
		
引 如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力. 此篇文章中也会简单阐述到栈 ...
 - 【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法
		
1 借用JSON对象的parse和stringify function deepClone(obj){ let _obj = JSON.stringify(obj), objClone = JSON. ...
 - 一步步分析Java深拷贝的两种方式-clone和序列化
		
今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clon ...
 - JS 中深拷贝的几种实现方法
		
JS 中深拷贝的几种实现方法1.使用递归的方式实现深拷贝 //使用递归的方式实现数组.对象的深拷贝 function deepClone1(obj) { //判断拷贝的要进行深拷贝的是数组还是对象,是 ...
 - 2种方法实现java对象的深拷贝
		
2种方法实现java对象的深拷贝 2017年12月03日 22:23:07 iCoding91 阅读数 4420更多 分类专栏: java 版权声明:本文为博主原创文章,遵循CC 4.0 BY-S ...
 - js对象的深拷贝及其的几种方法
		
深拷贝和浅拷贝是javascript中一个比较复杂的问题,也是面试官最喜欢问的问题之一,通过这个为可以看出是否入门,深拷贝和浅拷贝也是初学者经常犯错一个点. 简单来说深拷贝是拷贝储存在栈中的对象,而浅 ...
 - 用浅/深拷贝、和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]; ...
 - JS 深拷贝和浅拷贝概念,以及实现深拷贝的三种方式
		
一.理解堆栈,基本数据类型与引用数据类型 1.堆栈 栈(stack):系统自动分配的内存空间,内存会由系统自动释放,用来存放函数的参数值,局部变量的值等,特点是先进后出. 堆(heap):系统动态分配 ...
 - JS 判断数据类型的三种方法
		
说到数据类型,我们先理一下JavaScript中常见的几种数据类型: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Functi ...
 
随机推荐
- vue-cli初始化项目
			
vue init webpack cnpm install npm run dev 初始化项目 我们用vue init命令来初始化项目,具体看一下这条命令的使用方法. vue init <t ...
 - CentOS 6.x 安装 JDK1.8
			
安装方式:rpm(此方式不需要手动配置环境变量) 1. 查看系统是否自带了jdk 查看centos是否自带了openjdk,如果有则卸载掉(当然也可以不卸载,但要注意冲突及版本的使用) # 查看 rp ...
 - 该如何真正进入SEO行业?
			
今天一个多年的朋友突然问我这个问题,他作为一个seo局外人,感觉SEO挺神秘,我认为要入行就要先了解一个SEO是什么职业,它的工作有那些,然后再考虑怎样进行学习或培训. 一.查看网站状态 seo人员每 ...
 - JAVA String类型的一些小操作
			
String类型是否包含某个String类型的函数:源字符串.contains(包含字符串) 返回值为:boolean类型(true或false) String类型把某个字符替换成另一个字符:源字符 ...
 - POJ 3183:Stump Removal(模拟)
			
http://poj.org/problem?id=3183 题意:有n个树桩,分别有一个高度h[i],要用Bomb把树桩都炸掉,如果炸的位置的两边树桩高度小于Bomb炸的树桩高度,那么小于树桩高度的 ...
 - 使用开源框架Sqlsugar结合mysql开发一个小demo
			
一.Sqlsugar简介 1.性能上有很大优势 sqlsugar是性能最好的ORM之一,具有超越Dapper的性能 ,走的是EMIT够构中间语言动态编译到程序集,完成高性能的实体绑定,达到原生水平. ...
 - 为什么Python 3.6以后字典有序并且效率更高?
			
在Python 3.5(含)以前,字典是不能保证顺序的,键值对A先插入字典,键值对B后插入字典,但是当你打印字典的Keys列表时,你会发现B可能在A的前面. 但是从Python 3.6开始,字典是变成 ...
 - Netty-新连接接入源码解读
			
本片博文来看Netty的服务端是如何处理新连接接入问题的 什么是新连接接入?以及新连接接入前,Netty处于什么状态 netty的服务端NioServerSocketChannel初始化,注册在Bos ...
 - 关于下载安装Photoshop CS6遇到的一些问题
			
关于安装Photoshop CS6顺带安装AdobeBridge CS6和Aobe Extension Manager CS6的问题 Bridge是PS的一款插件,它能兼容大多数AODBE公司的软件, ...
 - C#中对EXCEL保存的SAVEAS方法说明
			
这两天做的导出报表的项目中,因为出现了一些问题所以对于excel一些方法参数有了一些认识, 首先:开始生成的是.xls格式的excel文件,但是某个sheet发现我本来dataTable的数据有8万多 ...