[c#基础]ICloneable接口

news/2024/7/6 2:43:33

摘要

该接口使你能够创建现有对象的副本的自定义的实现。该接口只提供了,一个Clone方法,实现对象的浅拷贝。有浅拷贝,那么就有相对应的深拷贝。但该接口并没有对我们提供,需要我们自己实现。

什么是浅拷贝与深拷贝?

浅拷贝

将对象的字段复制到新的对象副本中,同时将字段的值也复制过去,但引用类型值复制引用,而不是引用类型本身,也就是,如果源对象的引用类型的字段的值改变了,拷贝的对象的对应的引用类型的字段也会跟着变化。

深拷贝

将对象的字段复制到新的对象副本中,无论是值类型还是引用类型的字段,都会复制类型本身及值。但,源对象的值变化,并不会影响副本中的对应的值。

一个例子

浅拷贝

using Newtonsoft.Json;
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;namespace Wolfy.CloneDemo
{class Program{static void Main(string[] args){Console.WriteLine("创建新对象:");Person p = new Person() { Name = "wolfy", Id = 1, Address = new Address { City = "北京", Details = "北京 海淀区" } };Console.WriteLine(p.ToString());Console.WriteLine("克隆对象:");Person p2 = (Person)p.Clone();Console.WriteLine(p2.ToString());var result = object.ReferenceEquals(p, p2);Console.WriteLine("p ReferenceEquals p2:" + result);Console.WriteLine("此时修改p对象,是否会影响p2对象?");p.Name = "wolfy2";p.Id = 2;p.Address.City = "上海";Console.WriteLine("p:" + p.ToString());Console.WriteLine("p2:" + p2.ToString());Console.Read();}}[Serializable]class Person : ICloneable{/// <summary>/// 值类型/// </summary>private int _id;/// <summary>/// 特殊的引用类型/// </summary>private string _name;private Address _address;public int Id { get => _id; set => _id = value; }public string Name { get => _name; set => _name = value; }public Address Address { get => _address; set => _address = value; }public override string ToString(){return JsonConvert.SerializeObject(this);}public object Clone(){/*MemberwiseClone方法创建的新对象,然后将当前对象的非静态字段复制到新的对象创建的浅表副本。如果字段是值类型,则执行字段的按位复制。 如果字段是引用类型,引用将复制,但被引用的对象不;因此,原始对象和其克隆引用同一对象。例如,考虑对象称为 X 引用对象 A 和 B,反过来,引用对象 c。X 的浅表副本创建新的对象 X2 也引用对象 A 和 b。与此相反,X 的深层副本创建新对象 X2 引用 A2 和 B2,是的一个副本的新对象并 B.B2,反过来,引用新对象 C2,这是 C 的副本。该示例说明浅和深层复制操作之间的差异。有很多方法可以实现深层复制操作,如果浅表复制操作由MemberwiseClone方法并不满足你的需求。这些要求包括:调用类构造函数要复制可以使用来自第一个对象的属性值创建第二个对象的对象。这假定,对象的值完全由其类构造函数中定义。调用MemberwiseClone方法创建一个对象,对象的浅表副本并将其值是与原始对象的任何属性或其值是引用类型的字段相同的新对象。DeepCopy方法在示例中演示了此方法。序列化对象是较深复制,,然后将序列化的数据还原到另一个对象变量。使用具有递归反射来执行深层复制操作。*/return this.MemberwiseClone();}public object DeepClone(){using (Stream objectStream = new MemoryStream()){IFormatter formatter = new BinaryFormatter();formatter.Serialize(objectStream, this);objectStream.Seek(0, SeekOrigin.Begin);return formatter.Deserialize(objectStream) as Person;}}}[Serializable]class Address{private string _city;private string _details;public string City { get => _city; set => _city = value; }public string Details { get => _details; set => _details = value; }}}

如上图所示,浅拷贝,值类型的并不会相互影响,但是引用类型的Address会跟着改变。浅拷贝,在对引用类型的字段时,会拷贝指向该对象的引用。

深拷贝

 Person p2 = (Person)p.Clone();

改为

 Person p2 = (Person)p.DeepClone();

结语

 在实际项目中,这个接口自己是没用过。在看c#相关的文章的时候,看到了该接口的介绍,一篇文章了解下。如果非要说应用场景的话,比如,如果一个方法参数是一个引用类型,你需要在方法中对其进行操作,但又不想改变它原有的值,可以实现该接口,在clone实现深拷贝,对拷贝的副本进行操作,不影响它的原有的值,返回一个新的对象。

转载于:https://www.cnblogs.com/wolf-sun/p/9087634.html


http://lihuaxi.xjx100.cn/news/272848.html

相关文章

纯css3代码写下拉菜单效果

1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <meta name"viewport" content"widthdevice-width,initial-scale1;user-scaleno">6 <title>CSS3树形菜单</title…

4招教你零基础入门Python

随着近几年Python的飞速发展&#xff0c;应用范围逐步趋于广泛&#xff0c;后端开发、前端开发、爬虫、金融量化分析、人工智能、自动化运维、自动化运维、大数据&#xff0c;Python都有涉及。Python相对其他编程语言来讲&#xff0c;语法较简单&#xff0c;就算没有任何编程基…

SQL查找是否存在,别再count了,很耗费时间的

点击上方“方志朋”&#xff0c;选择“设为星标”回复”666“获取新整理的面试文章来源&#xff1a;http://suo.im/5T1tGv根据某一条件从数据库表中查询 『有』与『没有』&#xff0c;只有两种状态&#xff0c;那为什么在写SQL的时候&#xff0c;还要SELECT count(*) 呢&#x…

机械键盘写代码嗖嗖嗖!免费包邮送到家

写代码如果用机械键盘是件很爽的事情&#xff0c;敲代码Bug多不多不重要&#xff0c;逼格必须先到位&#xff01;所以&#xff0c;小编联合9位公众号主给大家送一款全新的RX-78-2高达有线办公键盘游戏樱桃轴机械键盘红轴。写代码逼格高&#xff01;赠送规则本次活动联合了9个号…

读《杜拉拉升职记》有感

读杜拉拉升职记有感1.一定要在核心部门任职&#xff0c;防止被边缘化2.劳心者治人&#xff0c;劳力者治于人干了活还受气怎么办&#xff1f;1.把每一个阶段的主要任务和安排的都做成清晰简明的表格&#xff0c;发给我的老板&#xff0c;告诉他如果有反对意见&#xff0c;在某某…

《评人工智能如何走向新阶段》后记(再续17)

由AI科技大本营下载自视觉中国258.2月15日阿里巴巴达摩院研发AI诊断技术 阿里达摩院联合阿里云研发一套全新的AI诊断技术&#xff0c;可在20秒内对新冠肺炎疑似病例CT影像做出分析判断&#xff0c;识别准确率达96%。 有了AI加持&#xff0c;通过NLP自然语言处理回顾性数据&…

利用OpenCV识别玻璃纤维织物劈缝缺陷

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达玻璃纤维织物是经编多轴向织物&#xff0c;由一层或多层平行的纱线按照尽可能多的方向交错而成的。织物具有一定的密实度和厚度&#xff0c;颜色一般为白色&#xff0c;生…

Angular:Promise.all()的具体应用

现有项目开发中&#xff0c;从后台获取数据用异步promise&#xff0c;可是异步的数据要顺序获取真的是好费劲啊&#xff0c;还好解锁了promise.all()&#xff0c;下面来看代码吧&#xff01; 遍历this.groupList通过groupID获取组内成员&#xff0c;将获取的成员push到finalAcc…