一个快速克隆方法引出深浅拷贝说明

2024-04-19 20:44

本文主要是介绍一个快速克隆方法引出深浅拷贝说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提供的代码是一个泛型扩展方法,用于对任意类型的对象T进行浅拷贝(shallow copy)。这个方法使用反射来调用对象的MemberwiseClone方法,该方法为所有字段(包括值类型和引用类型字段)创建新的副本,但不复制引用类型字段所引用的对象。换句话说,它执行的是一个成员级的克隆,对于引用类型的字段,它复制的是引用本身,而不是引用的对象。

下面是该方法的详细解释:

public static T Clone<T>(this T obj)  
{  // 获取obj的类型  Type type = obj.GetType();  // 查找名为"MemberwiseClone"的方法,该方法是非公共的(即受保护的或私有的),并且是实例方法  MethodInfo method = type.GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);  // 如果找到了这个方法,则调用它并传递obj作为参数(即原对象本身)  // 由于MemberwiseClone不需要任何参数,所以第二个参数是null  object clonedObj = method?.Invoke(obj, null);  // 将返回的object类型转换为泛型类型T,并返回  return (T)clonedObj;  
}

要使用这个方法,你只需在支持MemberwiseClone方法的任何对象上调用它。
在C#中,MemberwiseClone方法是定义在System.Object类中的受保护(protected)成员。这意味着所有在C#中定义的类都隐式地继承了这个方法,因为所有的类最终都继承自System.Object。由于MemberwiseClone是受保护的,它只能在当前类或其派生类中被直接调用。如果要在类的外部使用它,通常需要通过反射(如示例所示)或将其封装为公共方法。

MemberwiseClone方法创建一个当前对象的浅拷贝(shallow copy),它会复制对象的所有字段到新的对象上,但是如果字段是引用类型,则复制的只是引用,而不是引用的对象本身。因此,对于引用类型的字段,原始对象和克隆后的对象将共享相同的引用。

class MyClass  
{  public int MyProperty { get; set; }  public string AnotherProperty { get; set; }  
}  class Program  
{  static void Main()  {  MyClass original = new MyClass { MyProperty = 1, AnotherProperty = "Hello" };  MyClass cloned = original.Clone(); // 使用扩展方法克隆对象  Console.WriteLine(cloned.MyProperty); // 输出: 1  Console.WriteLine(cloned.AnotherProperty); // 输出: Hello  // 注意:如果MyClass中有引用类型的字段,这些字段在克隆对象中将仍然指向原始对象中的相同实例。  }  
}

需要注意的是,MemberwiseClone方法创建的是浅拷贝,这意味着如果对象包含引用类型的字段,那么这些字段在克隆后的对象中将仍然引用原始对象中的相同实例。如果你需要深拷贝(deep copy),即复制对象及其所有引用类型字段所引用的对象,那么你需要实现自定义的深拷贝逻辑,这通常涉及递归地复制对象的所有字段,并对引用类型字段进行深拷贝。

在C#中,实现深度克隆(深拷贝)的方法有多种。深度克隆不仅复制对象的值类型字段,还复制原对象中的对象,即完全创建新对象。以下是几种实现深度克隆的常见方法:

使用序列化与反序列化:
通过将对象序列化为一个中间格式(如JSON或XML),然后再从该格式反序列化回来,可以实现深度克隆。这种方法可以处理对象的复杂结构,包括嵌套的对象和集合。但是,它要求对象及其所有成员都是可序列化的,并且可能会受到序列化格式的限制。

使用自定义的递归拷贝方法:
通过递归地遍历对象的所有字段和属性,并为每个字段和属性创建新的副本,可以实现深度克隆。这种方法需要编写更多的代码,并且需要处理各种数据类型和复杂情况(如循环引用)。

使用第三方库:
有些第三方库提供了深度克隆的功能,可以简化深度克隆的实现。例如,AutoMapper、DeepCopy等库都提供了深度克隆的功能。

使用反射:
与MemberwiseClone方法类似,反射也可以用来实现深度克隆。通过反射获取对象的所有字段和属性,并递归地创建它们的副本,可以实现深度克隆。但是,这种方法性能较低,且代码复杂度高。

这篇关于一个快速克隆方法引出深浅拷贝说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/918448

相关文章

Python安装Pandas库的两种方法

《Python安装Pandas库的两种方法》本文介绍了三种安装PythonPandas库的方法,通过cmd命令行安装并解决版本冲突,手动下载whl文件安装,更换国内镜像源加速下载,最后建议用pipli... 目录方法一:cmd命令行执行pip install pandas方法二:找到pandas下载库,然后

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

SQL Server安装时候没有中文选项的解决方法

《SQLServer安装时候没有中文选项的解决方法》用户安装SQLServer时界面全英文,无中文选项,通过修改安装设置中的国家或地区为中文中国,重启安装程序后界面恢复中文,解决了问题,对SQLSe... 你是不是在安装SQL Server时候发现安装界面和别人不同,并且无论如何都没有中文选项?这个问题也

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分

Spring Boot从main方法到内嵌Tomcat的全过程(自动化流程)

《SpringBoot从main方法到内嵌Tomcat的全过程(自动化流程)》SpringBoot启动始于main方法,创建SpringApplication实例,初始化上下文,准备环境,刷新容器并... 目录1. 入口:main方法2. SpringApplication初始化2.1 构造阶段3. 运行阶

mybatis-plus QueryWrapper中or,and的使用及说明

《mybatis-plusQueryWrapper中or,and的使用及说明》使用MyBatisPlusQueryWrapper时,因同时添加角色权限固定条件和多字段模糊查询导致数据异常展示,排查发... 目录QueryWrapper中or,and使用列表中还要同时模糊查询多个字段经过排查这就导致只要whe

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法

《Python错误AttributeError:NoneTypeobjecthasnoattribute问题的彻底解决方法》在Python项目开发和调试过程中,经常会碰到这样一个异常信息... 目录问题背景与概述错误解读:AttributeError: 'NoneType' object has no at

postgresql使用UUID函数的方法

《postgresql使用UUID函数的方法》本文给大家介绍postgresql使用UUID函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录PostgreSQL有两种生成uuid的方法。可以先通过sql查看是否已安装扩展函数,和可以安装的扩展函数