理解C#中对象的浅拷贝和深拷贝
本文章主要介绍C#中对象的拷贝,其中包括浅拷贝和深拷贝,以及浅拷贝和深拷贝的实现方式,不同的实现方式之间的性能对比。
1、浅拷贝和深拷贝
浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值他将反映在原是对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对象中对应字段的内容。
2、浅拷贝实现方式
1)new对象赋值
[Serializable]
class Employee
{public string ID { get; set; }public int Age { get; set; }public Department DepartmentName { get; set; }
}
[Serializable]
class Department
{public string DepartmentName { get; set; }public Department(string value){DepartmentName = value;}public override string ToString(){return DepartmentName.ToString();}
}
Employee emp1 = new Employee()
{ID = "cjavapy",Age = 20,DepartmentName = new Department("develop")
}
;
Employee emp2=new Employee()
{ID=emp1.ID,Age=emp1.Age,DepartmentName=emp1.DepartmentName
};
2)实现ICloneable接口
class Employee : ICloneable
{public string ID { get; set; }public int Age { get; set; }public Department DepartmentName { get; set; }//实现ICloneable接口的Clone方法public object Clone(){return this.MemberwiseClone();//浅拷贝}
}
class Department
{public string DepartmentName { get; set; }public Department(string value){DepartmentName = value;}public override string ToString(){return DepartmentName.ToString();}
}
浅拷贝:
Employee emp1 = new Employee()
{ID = "cjavapy",Age = 20,DepartmentName = new Department("develop")
};
Employee emp2 = emp1.Clone() as Employee;//浅拷贝
3、深拷贝实现方式
1)二进制序列化
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using Newtonsoft.Json;namespace ConsoleApplication
{public class Utils{public static T BinaryClone<T>(T source){if (!typeof(T).IsSerializable){throw new ArgumentException("需要添加[Serializable]标签", "source");}if (Object.ReferenceEquals(source, null)){return default(T);}IFormatter formatter = new BinaryFormatter();Stream stream = new MemoryStream();using (stream){formatter.Serialize(stream, source);stream.Seek(0, SeekOrigin.Begin);return (T)formatter.Deserialize(stream);}}}}
2)JSON序列化
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using Newtonsoft.Json;namespace ConsoleApplication
{public class Utils{/// /// 序列化反序列化方式/// /// /// public static TOut JsonClone<TIn,TOut>(TIn tIn){return JsonConvert.DeserializeObject<TOut>(JsonConvert.SerializeObject(tIn));}}}
3)Reflection反射
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{public class Utils{/// /// 反射实现深拷贝/// /// 传入TIn对象返回TOut对象/// public static TOut ReflectionClone<TIn, TOut>(TIn tIn){TOut tOut = Activator.CreateInstance<TOut>();foreach (var itemOut in tOut.GetType().GetProperties()){var propIn = tIn.GetType().GetProperty(itemOut.Name);itemOut.SetValue(tOut, propIn.GetValue(tIn));}foreach (var itemOut in tOut.GetType().GetFields()){var fieldIn = tIn.GetType().GetField(itemOut.Name);itemOut.SetValue(tOut, fieldIn.GetValue(tIn));}return tOut;}/// <summary>/// 传入List<TIn>,返回List<TOut>/// </summary>/// <typeparam name="TIn"></typeparam>/// <typeparam name="TOut"></typeparam>/// <param name="tInList"></param>/// <returns></returns>public static List<TOut> ReflectionCloneList<TIn, TOut>(List<TIn> tInList){List<TOut> result = new List<TOut>();foreach (var tIn in tInList){TOut tOut = Activator.CreateInstance<TOut>();foreach (var itemOut in tOut.GetType().GetProperties()){var propIn = tIn.GetType().GetProperty(itemOut.Name);itemOut.SetValue(tOut, propIn.GetValue(tIn));}foreach (var itemOut in tOut.GetType().GetFields()){var fieldIn = tIn.GetType().GetField(itemOut.Name);itemOut.SetValue(tOut, fieldIn.GetValue(tIn));}result.Add(tOut);}return result;}}public class ContactPerson{public string Name { get; set; }public string MobileNum { get; set; }}class Program{static void Main(string[] args){var persons = new List<ContactPerson>{new ContactPerson { Name= "C", MobileNum = "13756863001"},new ContactPerson { Name = "C#", MobileNum = "13756863002"},new ContactPerson { Name = "Java", MobileNum = "13756863003"}};var result = Utils.ReflectionCloneList<ContactPerson, ContactPerson>(persons);foreach(var p in result)Console.WriteLine("姓名: {0} 号码为: {1}", p.Name, p.MobileNum);Console.Read();}}
}
4)XML序列化
using System.IO;
using System.Xml.Serialization;namespace ConsoleApplication
{public class Utils{public static T DeserializeXML<T>(string xmlData) where T : new(){if (string.IsNullOrEmpty(xmlData))return default(T);TextReader tr = new StringReader(xmlData);T DocItms = new T();XmlSerializer xms = new XmlSerializer(DocItms.GetType());DocItms = (T)xms.Deserialize(tr);return DocItms == null ? default(T) : DocItms;}}
}
5)表达式目录树
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{/// <summary>/// 生成表达式目录树 泛型缓存/// </summary>/// <typeparam name="TIn"></typeparam>/// <typeparam name="TOut"></typeparam>public class ExpressionGenericMapper<TIn, TOut>//`2{private static Func<TIn, TOut> _FUNC = null;static ExpressionGenericMapper(){ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");List<MemberBinding> memberBindingList = new List<MemberBinding>();foreach (var item in typeof(TOut).GetProperties()){MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));MemberBinding memberBinding = Expression.Bind(item, property);memberBindingList.Add(memberBinding);}foreach (var item in typeof(TOut).GetFields()){MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));MemberBinding memberBinding = Expression.Bind(item, property);memberBindingList.Add(memberBinding);}MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]{parameterExpression});_FUNC = lambda.Compile();//}public static TOut Trans(TIn t){return _FUNC(t);}}
}
4、拷贝方式性能对比
对比代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Newtonsoft.Json;namespace ConsoleApplication
{class Program{static void Main(string[] args){Employee emp1 = new Employee(){ID = "cjavapy",Age = 20,DepartmentName = new Department("develop")};long common = 0;long expression = 0;long json = 0;long xml = 0;long binary = 0;long reflection = 0;{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 1000000; i++){Employee copy = BinaryClone<Employee>(emp1);}watch.Stop();binary = watch.ElapsedMilliseconds;}{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 1000000; i++){Employee copy = ReflectionClone<Employee, Employee>(emp1);}watch.Stop();reflection = watch.ElapsedMilliseconds;}{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 1000000; i++){Employee copy = DeserializeXML<Employee>(SerializeXML<Employee>(emp1));}watch.Stop();xml = watch.ElapsedMilliseconds;}{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 1000000; i++){Employee copy = JsonClone<Employee, Employee>(emp1);}watch.Stop();json = watch.ElapsedMilliseconds;}{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 1000000; i++){Employee copy = ExpressionGeneric<Employee, Employee>.Clone(emp1);}watch.Stop();expression = watch.ElapsedMilliseconds;}Console.WriteLine($"binary = { binary} ms");Console.WriteLine($"reflection = { reflection} ms");Console.WriteLine($"serialize = { xml} ms");Console.WriteLine($"json = { json} ms");Console.WriteLine($"generic = { expression} ms");Console.ReadKey();}public static T BinaryClone<T>(T source){if (!typeof(T).IsSerializable){throw new ArgumentException("需要添加[Serializable]标签", "source");}if (Object.ReferenceEquals(source, null)){return default(T);}IFormatter formatter = new BinaryFormatter();Stream stream = new MemoryStream();using (stream){formatter.Serialize(stream, source);stream.Seek(0, SeekOrigin.Begin);return (T)formatter.Deserialize(stream);}}/// <summary>/// 反射/// </summary>/// <typeparam name="TIn"></typeparam>/// <typeparam name="TOut"></typeparam>/// <param name="tIn"></param>/// <returns></returns>public static TOut ReflectionClone<TIn, TOut>(TIn tIn){TOut tOut = Activator.CreateInstance<TOut>();foreach (var itemOut in tOut.GetType().GetProperties()){var propIn = tIn.GetType().GetProperty(itemOut.Name);itemOut.SetValue(tOut, propIn.GetValue(tIn));}foreach (var itemOut in tOut.GetType().GetFields()){var fieldIn = tIn.GetType().GetField(itemOut.Name);itemOut.SetValue(tOut, fieldIn.GetValue(tIn));}return tOut;}public static TOut JsonClone<TIn, TOut>(TIn tIn){return JsonConvert.DeserializeObject<TOut>(JsonConvert.SerializeObject(tIn));}public static string SerializeXML<T>(T t){using (StringWriter sw = new StringWriter()){XmlSerializer xz = new XmlSerializer(t.GetType());xz.Serialize(sw, t);return sw.ToString();}}public static T DeserializeXML<T>(string xmlData) where T : new(){if (string.IsNullOrEmpty(xmlData))return default(T);TextReader tr = new StringReader(xmlData);T DocItms = new T();XmlSerializer xms = new XmlSerializer(DocItms.GetType());DocItms = (T)xms.Deserialize(tr);return DocItms == null ? default(T) : DocItms;}}[Serializable]public class Employee : ICloneable{public string ID { get; set; }public int Age { get; set; }public Department DepartmentName { get; set; }//实现ICloneable接口的Clone方法public object Clone(){return this.MemberwiseClone();//浅拷贝}}[Serializable]public class Department{public string DepartmentName { get; set; }public Department(){}public Department(string value){DepartmentName = value;}public override string ToString(){return DepartmentName.ToString();}}/// <typeparam name="TIn"></typeparam>/// <typeparam name="TOut"></typeparam>public class ExpressionGeneric<TIn, TOut>//Mapper`2{private static Func<TIn, TOut> _FUNC = null;static ExpressionGeneric(){ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");List<MemberBinding> memberBindingList = new List<MemberBinding>();foreach (var item in typeof(TOut).GetProperties()){MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));MemberBinding memberBinding = Expression.Bind(item, property);memberBindingList.Add(memberBinding);}foreach (var item in typeof(TOut).GetFields()){MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));MemberBinding memberBinding = Expression.Bind(item, property);memberBindingList.Add(memberBinding);}MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]{parameterExpression});_FUNC = lambda.Compile();}public static TOut Clone(TIn t){return _FUNC(t);}}
}
相关文章:
理解C#中对象的浅拷贝和深拷贝
本文章主要介绍C#中对象的拷贝,其中包括浅拷贝和深拷贝,以及浅拷贝和深拷贝的实现方式,不同的实现方式之间的性能对比。 1、浅拷贝和深拷贝 浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它…...
js 生成随机数(含随机颜色)
生成 0-1 之间的随机数 Math.random()生成 0-x 之间的随机整数: Math.round(Math.random()*x)生成 min-max 之间的随机整数: Math.round(Math.random()*(max-min)min)生成N位随机数 /*** 函数--生成N位随机数* param {*} N 数字的长度*/ function random…...
【axios】axios的基本使用
一、 Axios简介 1、 Axios是什么? Axios是一个基于promise的HTTP库,类似于jQuery的ajax,用于http请求。可以应用于浏览器端和node.js,既可以用于客户端,也可以用于node.js编写的服务端。 2.、Axios特性 支持Promis…...
React 在非组件环境切换路由
我的react-router-dom版本是6.16.0。之前在react中是这样配置路由的 App.jsx import ReactDOM from react-dom/client; import { HashRouter, Route, Routes } from react-router-dom;const root ReactDOM.createRoot(document.getElementById("app")); root.rend…...
Oracle高速批量速插入数据解决方案
最近做短信群发项目有一个需求,需要客户大批量(十万级)导入数据. 开始是用insert单条数据,10万条数据要20分钟 后来发现可以用insert all 一条sql一次导入500条记录,这样10万条数据只用了1.5分钟,导入速度提高了近来20倍 下面就使用insert all的心得体会记录如下. 使用方法: i…...
基于单片机嵌入式的智能交通信号灯管理系统的设计与实现
项目介绍 有目共睹电子设备已经席卷了整个人类生活,他们不断改善着人们的起居住行,这也就促进了嵌入式人工智能的快速发展。 本课设模拟系统分为软硬件两部分组成。硬件部分是由两位8段数码管和LED灯构成的显示系统和控制电路等组成,能较好的…...
在全新ubuntu上用gpu训练paddleocr模型遇到的坑与解决办法
目录 一. 我的ubuntu版本二.首先拉取paddleocr源代码三.下载模型四.训练前的准备1.在源代码文件夹里创造一个自己放东西的文件2.准备数据2.1数据标注2.2数据划分 3.改写yml配置文件4.…...
React之服务端渲染
一、是什么 在SSR中 (opens new window),我们了解到Server-Side Rendering ,简称SSR,意为服务端渲染 指由服务侧完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可…...
jetson nano刷机更新Jetpack
只是记录个人在使用英伟达jetson Nano的经历,由于头一次尝试,所以特此记录需要的问题和经验。 一,英伟达刷机教程(jetson nano 版本) 本次我是直接刷机到TF卡,然后TF卡作为启动盘进行启动,我看网上有带EMMC版本的,好像可以直接把系统镜像安装到EMMC里面。但是有个问题…...
Android官方ShapeableImageView描边/圆形/圆角图,xml布局实现
Android官方ShapeableImageView描边/圆形/圆角图,xml布局实现 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.…...
ubuntu扩大运行内存, 防止编译卡死
首先查看交换分区大小 grep SwapTotal /proc/meminfo 1、关闭交换空间 sudo swapoff -a 2、扩充交换空间大小,count64就是64G 1G x 64 sudo dd if/dev/zero of/swapfile bs1G count64 3、设置权限 sudo chmod 600 /swapfile 4、指定交换空间对应的设备文件 …...
Kafka集群修改单个Topic数据保存周期
在大数据部门经常使用Kafka集群,有的时候大数据部门可能在Kafka中的Topic数据保存时间不需要很长,一旦被消费后就不需要一直保留。默认Topic存储时间为7day,个别的Topic或者某台Kafka集群需要修改Topic数据保存的一个周期,调整为3…...
selenium模拟登录无反应
在使用自动化工具selenium时对某些网站登录界面send_keys输入账号密码,运行时却没有自己想要的结果出现,这是因为你碰到前端二般的开发人员,他们用的是HTML嵌套,这对后端人员造成了一些麻烦,废话不多说,直接…...
指针变量未分配空间或者初始化为空指针使用问题
提示:关于指针 文章目录 前言一、指针的使用总结 前言 在看c书籍的时候,看到浅复制和深复制时,说到成员为指针的时候,会出异常。但是其实没有更多的感想,但是联想到上次考试指针没分配空间导致程序异常的情况…...
力扣第763题 划分字母区间 c++ 哈希 + 双指针 + 小小贪心
题目 763. 划分字母区间 中等 相关标签 贪心 哈希表 双指针 字符串 给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 注意,划分结果需要满足:将所有划分结果按顺序连接,得…...
js 代码中的 “use strict“; 是什么意思 ?
use strict 是一种 ECMAscript5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行。 设立"严格模式"的目的,主要有以下几个: 消除 Javascript 语法的一些不合理、不严谨之处,…...
用于读取验证码的 OCR 模型
介绍 此示例演示了使用功能 API 构建的简单 OCR 模型。除了结合 CNN 和 RNN 之外,它还说明了如何实例化新层并将其用作“端点层”来实现 CTC 损失。 设置 import os import numpy as np import matplotlib.pyplot as pltfrom pathlib import Path from collections import Co…...
Uniapp 跳转回上一页面并刷新页面数据
比如我从A页面跳转到B页面 然后再从B页面返回到A页面 顺带刷新一下A页面数据 let pages getCurrentPages(); // 当前页面 //获取当前页面栈let beforePage pages[pages.length - 3]; // //获取上一个页面实例对象beforePage.$vm.reloadList(); //调用它方法然后跳转…...
DeOldify 接口化改造 集成 Flask
类似的图片修复项目 GFPGAN 的改造见我另一篇文 https://blog.csdn.net/weixin_43074462/article/details/132497146 DeOldify 是一款开源软件,用于给黑白照片或视频上色,效果还不错。 安装部署教程请参考别的文章,本文基于你给项目跑通&…...
Vue 3响应式对象: ref和reactive
目录 什么是响应式对象? Ref Reactive Ref vs Reactive 适用场景: 访问方式: 引用传递: 性能开销: 响应式对象优点 响应式对象缺点 总结 Vue 3作为一种流行的JavaScript框架,提供了响应式编程的…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
