zoukankan      html  css  js  c++  java
  • 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;
    }

  • 相关阅读:
    python简单应用!用爬虫来采集天猫所有优惠券信息,写入本地文件
    python有哪些好玩的应用实现,用python爬虫做一个二维码生成器
    Python学习,给自己的代码做个合集,定制自己的桌面软件!
    用python抓取“3d”彩票数据,怎么分析你说了算!
    怎么让你的代码更Pythonic?光有技巧可不行,你还需要看这些
    Python学习汇总,做数据采集的一些小技巧,干货满满
    Python学习,还在用正则或者bs4做爬虫吗?来试试css选择器吧
    C# Windows API判断当前窗口是否与其他窗口有重叠(USER32.dll、dwmapi.dll)
    asp.net mvc 设置文本框的宽高
    C++ 判断当前系统x64 or x86
  • 原文地址:https://www.cnblogs.com/luoocean/p/10441587.html
Copyright © 2011-2022 走看看