首页 > 编程语言 >C#深复制

C#深复制

时间:2023-06-27 20:14:51浏览次数:37  
标签:bf obj C# 复制 ms 序列化 retval

转载:(29条消息) C#中4种深拷贝方法介绍_dotNET跨平台的博客-CSDN博客

我们有的时候会需要将一个数据类整个复制一个新的出来,并且新的数据和原数据互不影响,这个时候就需要使用深拷贝。常用的方法就是用反射序列化和反序列化实现。

1.反射

这种方法用的最多,因为可以自己控制数据类中哪些类型需要深复制。而且适用的场景多,比如一个复杂的数据类(内部引用了很多其他类型的实例),使用序列化的方法就要保证该数据类及其所引用的数据类型也需要支持序列化,但可能其引用的类型无法支持序列化(例如unity的一些原生的类)或者这次深复制只需要复制其引用的类型实例的引用即可,不需要重新创建一个新的,这些情况下就十分适合使用反射。

public static T DeepCopy<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.Instance | BindingFlags.Static);
  foreach (FieldInfo field in fields)
  {
//将其引用的类型实例也深复制一份新的
    try { field.SetValue(retval, DeepCopy(field.GetValue(obj))); }
    catch { }
//不复制其引用的类型实例,只是复制一份引用
    try { field.SetValue(retval, field.GetValue(obj)); }
    catch { }
  }
  return (T)retval;
}

2.二进制序列化和反序列化实现

public static T DeepCopy<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;
}

这种方法有些限制:

参与序列化的类引用了Transform或者继承了MonoBehaviour,会报无法序列化的错。

3.二进制序列化和反序列化实现

public static T DeepCopy<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;
}

限制:

无法直接对Unity的数据如,vector3, quaternion等使用BinaryFormatter进行序列化,会报“SerializationException: Type UnityEngine.Vector3 is not marked as Serializable”。当然解决办法也有。比如对vector3, quaternion重新包装一下。

标签:bf,obj,C#,复制,ms,序列化,retval
From: https://www.cnblogs.com/mcyushao/p/17509803.html

相关文章

  • Asp.net core使用Razor试图引擎编写TagHelper
    之前使用wtm来进行快速开发wtm框架见:https://wtmdoc.walkingtec.cn/其前端选择Layui的情况下有大量的TagHelper,大幅度提高了开发效率 虽然已有的组件很丰富但也不能完全覆盖所有的需求,这个时候就需要自己写TagHelper。参考了WTM源码,和微软官方文档TagHelper虽然使用起来方......
  • Python | 魔法函数`__contains__`的用法
    在python的字符串、列表、元组、结合等对象的时候,经常使用in的方法,一个类的对象能够使用in,就是因为这个类实现了__contains__魔法函数如下面的代码,演示了类的对象使用in的情形classStudent():def__init__(self,name):self.name=namedef__contains__(self......
  • Docker 安装 MongoDB
    Docker安装MongoDBDocker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化。访问ExploreDocker'sContainerImageRepository|DockerHub,搜索mongo镜像https:/......
  • Oracle 11.2.0.3 ORA-12012ORA-29280 ORA-06512
    Oracle11.2.0.3ORA-12012ORA-29280ORA-06512问题现象:dbalert日志中出现如下告警信息:Errorsinfile/app/oracle/diag/rdbms/cctv/CCTV2/trace/CCTV2_j000_1370.trc:ORA-12012:erroronautoexecuteofjob"ORACLE_OCM"."MGMT_CONFIG_JOB_2_2"ORA......
  • 1、Elasticsearch单机与集群的安装(包安装、二进制安装与Docker安装)
    ElasticsearchElasticsearch是一个实时的全文搜索,存储库和分析引擎https://www.elastic.co/cn/what-is/elasticsearchElasticsearch在速度和可扩展性方面都表现出色,而且还能够索引多种类型的内容,可用于多种场景:应用程序搜索网站搜索企业搜索日志处理和分析基础设施指标和......
  • TCP相关知识
    1、TCP可靠传输是怎么实现的?TCP(TransmissionControlProtocol,传输控制协议)是一种面向连接的、可靠的传输协议。在TCP中,可靠传输是通过以下几种机制来实现的:序列号和确认应答机制:在TCP通信过程中,每个数据包都有一个唯一的序列号。接收方通过确认应答机制来告诉发送方已经正......
  • [ABC307G] Approximate Equalizatio
    [ABC307G]ApproximateEqualizatio题意给定一个数组\(a_i\),有两种操作。\(a_i+1,a_{i+1}-1\)\(a_i-1,a_{i+1}+1\)问最少花费多少次操作能使数组的极差不超过\(1\)。题解题目其实并不难,容易发现总和不变,由于极差不超过\(1\),设平均数为\(s\),则数组中只有\(s\)和......
  • TreeSaver 使用教程整理——Step 3: Creating Grids
    请首先阅读前几篇教程,才能对本篇文章了解比较深入:TreeSaver使用教程整理——Step1:GettingStartedTreeSaver使用教程整理——Step2:AddingBasicUI我们在第二步的基础上,copy到step3作为我们step3初始的基础。 Step3:CreatingGrids模板文件resources.html的变化在......
  • TreeSaver 使用教程整理——Step 2: Adding Basic UI
    请首先阅读前一篇教程:TreeSaver使用教程整理——Step1:GettingStartedStep2:AddingBasicUI我们上一步实现的网页有了一个最最简单的功能,这一步我们将在上一步基础上添加切换分页的按钮以及显示当前页面信息。请Copy上一步的内容,并对下面文件做如下修改: 对资源文件(resource......
  • CAP理论
    CAP理论:CAP理论:一个牺牲一致性来换取可用性的实例  a:初始状态:b:正常执行过程c:更新传播失败时的执行过程在面对CAP问题有以下几种选择:不同产品在CAP理论下的不同设计原则: ......