当前位置: 首页 > article >正文

详解 c# 克隆

克隆方法是原型设计模式中必须使用的方式,它将返回一个与当前对象数据一致的对象。正如其名,犹如一个模子雕刻而出。克隆类型分为两种:浅克隆、深克隆。

1、浅克隆

浅克隆方式是最简单、最直接的方式。只需要类实现接口ICloneable(在命名空间System.Runtime.InteropServices下)的Clone方法,在方法中使用加入对当前类的MemberwiseClone()方法即可。在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象。

在这里插入图片描述

如:

public class Student:ICloneable
{/// <summary>/// 值类型/// </summary>public int ID { get; set; }   /// <summary>/// 引用类型/// </summary>public object obj { get; set; }public object Clone(){return this.MemberwiseClone();}
}

以上方法实现了对类对象的浅克隆方式。但是在该类中具有引用类型字段,浅克隆方法无法对引用字段进行克隆,引用字段仅仅是对其进行了地址引用。所以,当修改原本或者副本的引用字段的数据时,另一个对象的引用对象的数据同样会变化。深克隆将有效的解决此问题。

2、深克隆

深克隆相对于浅克隆方式比较复杂。深克隆是无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

在这里插入图片描述

深克隆实现的机制是将对象进行序列化为数据后,再次将数据反序列化为新的对象。序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。注意,在实现序列化前需要在类的上方标记为可序列化。本文采用的序列化方式为二进制序列化。

主要实现的代码如下:

[Serializable]//标记特性:可序列化public class Student{/// <summary>/// 值类型/// </summary>public int ID { get; set; }/// <summary>/// 引用类型/// </summary>public object obj { get; set; }public Student Clone( ){Student clone = new Student();using (Stream stream = new MemoryStream()){IFormatter formatter = new BinaryFormatter();try{formatter.Serialize(stream, this);stream.Seek(0, SeekOrigin.Begin);clone = formatter.Deserialize(stream) as Student;}catch (SerializationException e){Console.WriteLine("Failed to serialize. Reason: " + e.Message);throw;}}return clone;}}

深克隆实现机制相对复杂、效率稍慢,但它克服了浅克隆方式的不足,使得克隆对象时将类中的引用类型数据完全克隆为新的对象,而不是引用原本中的对象。如此,在修改双方的引用类型对象的数据时不会对另一方造成干扰。

但为每一个类都实现克隆方式,而重复书写相同代码未免麻烦。因此引入泛型方法。

3、泛型方法实现克隆

泛型的出现使得可以良好的解决在多个类或结构vb.net教程体中都需要进行克隆时重复编写代码的麻烦。在外部只需要使用相关方法即可。其代码如下:

public class Clone{/// <summary>/// 深克隆/// </summary>/// <typeparam name="T"></typeparam>/// <param name="t"></param>/// <returns></returns>public static T DepthClone<T>(T t){T clone = default(T);using (Stream stream = new MemoryStream()){IFormatter formatter = new BinaryFormatter();try{formatter.Serialize(stream, t);stream.Seek(0, SeekOrigin.Begin);clone = (T)formatter.Deserialize(stream);}catch (SerializationException e){Console.WriteLine("Failed to serialize. Reason: " + e.Message);throw;}}return clone;}}

在外部使用的方法如下:

Student stu1 = new Student();//实例化一个对象
stu1.obj = new object();//实例化对象中的引用对象
Student stu2 = Clone.DepthClone(stu1);//深克隆对象

4、扩展方法

扩展方法的出现可以很好的解决类自身直接调用克隆方法,而不需要调用静态类的方法,返回对象值。但其本身与泛型方法类似,不过为了使所有类都能使用定义的深克隆方法,此处使用对顶级类Object进行方法的扩展,其返回的值也是object类型。具体方法如下:

/// <summary>/// 注:扩展方法必须在静态类中/// </summary>public static class Clone{/// <summary>/// 深克隆/// </summary>/// <param name="obj">原始版本对象</param>/// <returns>深克隆后的对象</returns>public static object DepthClone(this object obj){object clone = new object();using (Stream stream = new MemoryStream()){IFormatter formatter = new BinaryFormatter();try{formatter.Serialize(stream, obj);stream.Seek(0, SeekOrigin.Begin);clone = formatter.Deserialize(stream);}catch (SerializationException e){Console.WriteLine("Failed to serialize. Reason: " + e.Message);throw;}}return clone;}}

使用方法示例:

Student stu1 = new Student();//实例化一个对象
stu1.obj = new object();//实例化对象中的引用对象
Student stu2 = stu1.DepthClone() as Student;//深克隆对象;注意:在此需要将object对象转换为我们需要的对象类型

以上就是详解 c# 克隆的详细内容

http://www.lryc.cn/news/2418132.html

相关文章:

  • 中国版Ubuntu操作系统:“麒麟” ubuntukylin-13.04-desktop
  • java位运算之移位运算
  • 51单片机学习记录-11-LCD1602
  • Linux常用命令及使用方法
  • android移动开发基础案例教程答案,渣本毕业两年经验,文末有彩蛋
  • 图片预览参考网址
  • ​【Socket】Java Socket编程基础及深入讲解​
  • 数字人解决方案——3D数字人从捕捉到建模与合成方法解析
  • 设备管理器里一片空白没有东西解决方法
  • 闪讯无线助手-Android端闪讯破解路由器拨号实现原理
  • fedora18装一些软件及配置
  • 2024亲测可用最新PHP仿猪八戒任务威客网整站源码/在线接任务网站源码
  • 360浏览器插件360抢票王火车票刷票技巧
  • 为什么南派三叔要封笔?
  • 数据库常见面试题(附答案)
  • F3arRa1n发布V4.2.1,完整绕过支持iOS14.5.1修复通知
  • NVIDIA官方中文版GPU编程指南v2.20(转载自GZeasy)
  • 一盒两用!——破解电信IPTV机顶盒为普通安卓机顶盒
  • 佳易王头疗养发护发馆会员管理系统试用版操作教程
  • Web服务器配置——搭建自己的web服务器,要求可以进行局域网内部的DNS地址解析。
  • 哈大客运专线起终点为现大连站五年左右建成通车
  • 使用阿里云轻量级服务器配置socket代理实现局域网远程访问
  • x264源代码简单分析:编码器主干部分-2
  • 生物药剂学与药物动力学习题1-15章
  • PDF转WORD工具破解版
  • TweenMax学习笔记整理
  • 试图共享文件夹时出现错误,没有启动服务器服务,此时尚未创建共享资源,试图共享时出现错误,没有启动服务器服务,此时尚未创建共享资源...
  • ENOENT raw.githubusercontent.com pngquant failed to build
  • MVVM大比拼之avalon.js源码精析
  • 用JSmooth转换可执行jar包为exe文件