摘要

该接口使你能够创建现有对象的副本的自定义的实现。该接口只提供了,一个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

[c#基础]ICloneable接口相关推荐

  1. TypeScript基础入门 - 接口 - 继承接口

    转载地址 TypeScript基础入门 - 接口 - 继承接口 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.0.13 为 ...

  2. spring中基础核心接口总结

    spring中基础核心接口总结 理解这几个接口,及其实现类就可以快速了解spring,具体的用法参考其他spring资料 1.BeanFactory最基础最核心的接口 重要的实现类有: XmlBean ...

  3. C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态

    C#基础--类/接口/成员修饰符,多态.重载.重写,静态和非静态 类/接口/成员修饰符 C#修饰符---接口: 接口默认访问符是internal 接口的成员默认访问修饰符是public C#修饰符-- ...

  4. 这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口

    前言 我们进行linq to sql和ef时代后,底层的实现基本使用的是repository模块,即仓储模式,事实上就是把ORM实体的最基本操作进行封闭,对外层不公开操作实现的细节. 面向接口的编程 ...

  5. Effective C#:避免使用ICloneable接口

    最近在学习Bill Wagner的书籍:<Effective C#:50 Specific Ways to Improve Your C#>,虽然是一本很早的书了,但是感觉很实用,并且跟国 ...

  6. TypeScript基础入门 - 接口 - 可索引的类型

    转载地址 TypeScript基础入门 - 接口 - 可索引的类型 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.0.11 ...

  7. Java基础-面向接口(interface)编程

    Java基础-面向接口(interface)编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的&q ...

  8. TypeScript基础入门 - 接口 - 简介

    转载地址 TypeScript基础入门 - 接口 - 简介 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.0.6 为了保证 ...

  9. CocosCreator新手教程——cc.Node基础常用接口(API)

    CocosCreator开发笔记--cc.Node基础常用接口(API) 一.常用属性 cc.Class({extends: cc.Component,properties: {sprite: {de ...

最新文章

  1. 数据结构----内存分配问题
  2. html 字号 宽度 像素,JS根据设备宽度设置根节点(html)font-size字体大小
  3. 高仿微信对话列表滑动删除效果
  4. Angular4.0.0正式发布,附新特性及升级指南
  5. mysql数据库latin1转utf8_三种转换Mysql数据库数据编码的窍门-latin1转utf8
  6. linux目录 文件 pdf,linux文件与目录管理.pdf
  7. 【数组】 - 有序数组设计
  8. 数据结构与算法--字符串的排列组合问题
  9. Android 4 2官方文档chm格式下载
  10. JavaScript算法(实例五)最大公约数和最小公倍数 / n的倍数之和 / 组合数
  11. 重载(overload)、覆盖(override)、隐藏(hide)的区别
  12. zabbix 3.0.7 for Centos 7.2 安装
  13. 移动app开发者必读:国内主要移动广告平台概况
  14. 有什么推荐的软件工程本科的毕业设计题目嘛?
  15. 经济学原理曼昆第八版课后习题答案
  16. excel连接mysql_使用Excel 通过 ODBC 连接到 MySQL 数据库
  17. Word如何删除最后一页空白页的五种方法
  18. linux oel7没有网络,sudo su命令不在OEL 7中工作(sudo su command not working in OEL 7)
  19. idea调试源代码c语言,IDEA阅读spring源码并调试
  20. ubuntu16.04修改DNS永久生效

热门文章

  1. 滴滴成立AI Labs 加大人工智能领域投入
  2. 终于放弃了Maven,我选择用Gradle!
  3. 昨天你用的 YYYY-MM-dd 被捶了吗?
  4. 秋招必备:斩获腾讯offer的简历分享!
  5. 高校青椒为避免相亲重复,给没谈成的124个姑娘每人建了个文件夹...
  6. 北大美女学霸力压大神何恺明新作MAE!怒摘12个SOTA,灵感竟来自16年前CVPR论文...
  7. 最新!TUI世界大学排名(2021)发布:清华位居全球前20名!
  8. CVPR 2021|一个绝妙的想法:在类别不平衡的数据上施展半监督学习
  9. 老师吴恩达,身家又增20亿
  10. 深度学习“三部曲”重磅资源、python、DL理论、工程实战全覆盖(附免费下载)...