ICloneable 接口 深拷贝 浅拷贝

SNN系列|编码篇(2)时序编码 Tempotral Coding 选择编码方法是要根据编码对象以及模型如何处理编码信息进行选择,如下是一种时序信息的编码对比: Threshold-based encoding 又称为tempotral contrast,该方法可以用于编解码一段序列,当差值超过阈值时发放脉冲,阈值是根据编码的序列自适应变化的。 使用该编码方法时,实值序列最好是沿时间变化的,因为在根据差分决定是否发放脉冲后,脉冲的顺序与差分顺序有关。 Time-to-first spike coding 该编码方法将信息用神经元首次 阅读详情
支持克隆,即用与现有实例相同的值创建类的新实例。

命名空间:  System
程序集:  mscorlib(在 mscorlib.dll 中)

语法
C# [ComVisibleAttribute(true)]public interface ICloneableICloneable 接口包含一个成员 Clone,它用于支持除 MemberwiseClone 所提供的克隆之外的克隆。

语法
C#

Object Clone()Clone 既可作为深层副本实现,也可作为浅表副本实现。在深层副本中,所有的对象都是重复的;而在浅表副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。

结果克隆必须与原始实例具有相同的类型或是原始实例的兼容类型。

 

ICloneable听起来是个好主意:可以为那些支持复制的类型实现ICloneable接口。如果不想支持复制,那就不要实现它。但是我们的类型并非活在真空中。让一个类型支持ICloneable接口会影响它的派生类。一旦类型支持ICloneable接口,那么它所有的派生类也都必须支持它。而且,其所有成员类型也都要支持ICloneable接口,或者有其他创建复制的机制。最后,当我们设计的类型包含交织成网状的对象时,支持深复制将变得很困难。ICloneable接口在其官方的定义里很巧妙地绕过了这个问题,其定义如下:ICloneable接口或者支持深复制(deep copy),或者支持浅复制(shallow copy)。浅复制指的是新对象包含所有成员变量的副本,如果成员变量为引用类型,那么新对象将和原对象引用同样的对象。深复制指的也是新对象包含所有成员变量的副本,但是所有引用类型的成员变量将被递归地克隆。对于C#的内建类型,例如整数,深复制和浅复制产生的是同样的结果。那么我们的类型应该支持哪一个?这要根据具体类型而定。但是在同一个对象中混合浅复制和深复制会导致许多不一致的问题。当涉足ICloneable接口时,这样的问题很难逃脱。大多数情况下,避免ICloneable接口反倒会获得一个比较简单的类——对类的客户来讲比较容易使用,对创建者来讲也比较容易实现。

任何只包含内建类型成员的值类型都不需要支持ICloneable接口;一个简单的赋值语句对struct的值所做的复制要比Clone()来得高效得多。Clone()必须对返回值进行装箱,才能转换为一个System.Object引用。调用者则必须进行强制转型才能获取真正的值。值类型默认的复制支持对我们来说已经足够了。我们没有必要再编写Clone()函数来重复这项工作。

如果值类型中包含引用类型呢?最明显的例子是包含字符串:

public struct ErrorMessage

{

private int errCode;

private int details;

private string msg;

// 忽略细节。

}

字符串是一个特殊的例子,因为string是一个具有常量性的类。如果我们对ErrorMessage对象进行赋值,两个ErrorMessage对象都将引用同一个字符串。但这并不会导致任何问题,而这放到一个普通的引用类型就会出现问题。通过任何一个对象更改msg变量,都会创建一个新的string对象(参见条款7)。

更一般的情况——创建一个包含任意引用类型变量的struct——就比较复杂了。不过这种情况相当少见。C#语言为struct提供的内建赋值操作创建的是一个浅复制——即两个struct引用的是同一个引用类型对象。要创建一个深复制,我们需要克隆其内包含的引用类型,而且需要确知其Clone()方法支持深复制。无论哪种情况,我们都没有必要为值类型添加ICloneable接口支持——赋值操作符可以创建任何值类型的新副本。

综上所述,对值类型来讲,提供ICloneable接口的理由不够充分。下面我们来看引用类型。引用类型要通过支持ICloneable接口来表明自身支持浅复制或者深复制。但是在为一个类添加ICloneable接口支持时,我们要审慎行事,因为那样做会强制要求该类的所有派生类也都必须支持ICloneable接口。考虑下面两个类:

class BaseType : ICloneable

{

private string _label = "class name";

private int [] _values = new int [ 10 ];

public object Clone()

{

    BaseType rVal = new BaseType( );

条款27:避免ICloneable接口 154

    rVal._label = _label;

    for( int i = 0; i < _values.Length; i++ )

      rVal._values[ i ] = _values[ i ];

    return rVal;

}

}

class Derived : BaseType

{

private double [] _dValues = new double[ 10 ];

static void Main( string[] args )

{

    Derived d = new Derived();

    Derived d2 = d.Clone() as Derived;

    if ( d2 == null )

      Console.WriteLine( "null" );

}

}

如果运行上面的程序,我们将发现d2的值为null。Derived类从BaseType类中继承了ICloneable.Clone()方法,但是继承来的实现对Derived类型来讲却是不正确的,因为它仅仅克隆了基类。BaseType.Clone()创建了一个BaseType对象,而非一个Derived对象。这就是测试程序中d2返回null的原因——它不是一个Derived对象。但是,即使我们能够克服这个问题,BaseType.Clone()也不能对Derived中定义的_dValues数组进行正确的复制。当我们的类型实现了ICloneable接口,就会强制要求其所有派生类也实现ICloneable接口。实际上,这时候我们应该提供一个挂钩函数(hook function)来允许所有派生类使用我们的实现(参见条款21)。为了支持克隆,派生类只可以添加那些支持ICloneable接口的值类型或引用类型成员变量。这对所有的派生类来说是一个非常严格的限制。因此我们说,为基类添加ICloneable接口支持通常会为其派生类带来一些负担,所以我们应该避免在非密封(nonsealed)类中实现ICloneable接口。

如果整个类层次必须实现ICloneable接口,我们可以创建一个抽象的Clone()方法,并强制要求所有的派生类实现它。

这时候,我们需要定义一种方式,使派生类可以创建基类成员的副本。这可以通过定义一个protected的复制构造器来实现:

class BaseType

{

private string _label;

private int [] _values;

protected BaseType( )

{

    _label = "class name";

    _values = new int [ 10 ];

}

// 供派生类用来做clone。

protected BaseType( BaseType right )

{

    _label = right._label;

    _values = right._values.Clone( ) as int[ ] ;

}

}

sealed class Derived : BaseType, ICloneable

{

private double [] _dValues = new double[ 10 ];

public Derived ( )

{

    _dValues = new double [ 10 ];

}

// 使用基类的“复制构造器”构造一个副本。

private Derived ( Derived right ) :

    base ( right )

{

    _dValues = right._dValues.Clone( )

      as double[ ];

}

static void Main( string[] args )

{

    Derived d = new Derived();

    Derived d2 = d.Clone() as Derived;

    if ( d2 == null )

      Console.WriteLine( "null" );

}

public object Clone()

{

    Derived rVal = new Derived( this );

    return rVal;

}

}

在上面的代码中,我们的基类BaseType没有实现ICloneable接口,但它提供了一个受保护的复制构造器,以使派生类可以复制其内的成员。如果有必要,“叶子类”——即那些密封类——可以实现ICloneable接口。我们的基类没有强制要求所有的派生类实现ICloneable接口,但它为所有希望实现ICloneable接口的派生类提供了必要的方法支持。

ICloneable接口有其价值所在,但那都是特例,而非普遍的规则。对于值类型来讲,我们永远都不需要支持ICloneable接口,使用默认的赋值操作就可以了。我们应该为那些确实需要复制操作的“叶子类”提供ICloneable接口支持。对于那些子类可能需要支持ICloneable接口的基类,我们应该为其创建一个受保护的复制构造器。除此之外,我们应该避免支持ICloneable接口


【Bluetooth蓝牙开发】九、BLE协议之GATT 1、开篇词 2、蓝牙开发入门 3、蓝牙协议栈总览 4、蓝牙协议栈——物理层 5、蓝牙协议栈——链路层 6、蓝牙协议栈——传输层 7、蓝牙协议栈——L2CAP协议 8、蓝牙协议栈——ATT协议 9、蓝牙协议栈——GATT协议 10、蓝牙通信流程分析 11、蓝牙协议栈——Bluez交叉编译 12、蓝牙调试工具汇总 阅读详情

相关推荐

MATPOWER的安装详细教程

MATPOWER的安装包实际为一个程序包,安装教程很简单,详见本文。

半个月亮Zz的博客 3万+

ICloneable和IComparable

对于所有面向对象的语言,复制永远是一个容易引发讨论的题目,C#中也不例外。此类问题在面试中极其容易被问到,我们应该在了解浅拷贝和深拷贝基本概念的基础上,从设计的角度进一步考虑如何支持对象的拷贝。

kalvin_y_liu的博客 897

【规则引擎连载3】 WebSphere ILOG JRules 开发——新建一个规则项目

规则项目依赖于bom,bom来自于一个Java项目,所以在建规则项目之前,需要先建立一个Java项目,也就是建模。 说明:原则上是一个规则项目,一个bom。如果规则项目很多,并且每个规则项目的bom都是一样的,那么可以将bom提取出来,单独作为一个项目,这样减少不必要的重复操作,减少维护成本,降低出错几率。这里逐步讲解两种方法来创建规则项目,推荐第二种。 本文主要建立两种规则项目与bom之间的关系,编写相关的规则内容,如操作规则、规则流、决策表等,在后续文章中详细讲解 。

manman的分享 2331

ICloneable深复制与浅复制

 http://hi.baidu.com/lovemyselfbest/blog/item/9e78bd01d0f1c1d2277fb587.htmlc# 深复制与浅复制2008/01/18 11:37 ICloneable听起来是个好主意:可以为那些支持复制的类型实现

735

私募pp网-私募排行js逆向

在数据采集的学习过程当中,发现了一个有意思的网站,所以记录一下,仅供学习交流,用于其他用途与作者无关。目标:私募基金当中的列表页数据。

zzp28218的博客 1896

树莓派驱动DLPDLCR230NPEVM+framebuffer显示图片

DLPDLCR230NPEVM DLP® LightCrafter™ Display 230NP 是一个易于使用的紧凑型即插即用评估平台,适用于消费类产品、工业、医疗和物联网 (IoT) 市场中的各种超便携显示应用。此评估模块 (EVM) 采用 DLP230NP 芯片组,该芯片组由DLP230NP.23 1080p DMD、DLPC3436显示控制器和DLPA2005PMIC/LED 驱动器组成。此 EVM 外形小巧,配备生产就绪型光学引擎以及支持 18 位 RGB 并行视频接口...

L_Y000的博客 2618

C# ICloneable的特点及其用法

在C#中,ICloneable是一个接口,用于定义允许一个对象创建自身的精确副本,即“克隆”的能力。ICloneableClone,该方法在实现时应该返回当前对象的一个副本。这里是ICloneable。

琅嬛福地 1603

雷电模拟器+Auto.js避坑指南:用桥接模式解决PC与模拟器连接超时问题

本文详细解析了雷电模拟器与Auto.js联调中的桥接模式应用,解决PC与模拟器连接超时问题。通过桥接模式配置、高频故障排查及多开环境下的高阶配置,提升开发效率与稳定性,特别适合需要稳定网络连接的Auto.js开发者。

weixin_28836989的博客 632

c#的System.ICloneable接口说明

System.ICloneable接口支持克隆,即用与现有实例相同的值创建类的新实例。msdn上的解释很简单,主要就是clone方法的实行,介绍深拷贝和浅拷贝,搞的很糊涂,那么到底是什么意思呢?看看下面的原理可能就会明白很多了。引自http://www.cnblogs.com/anderslly/archive/2007/04/08/implementingcloneabletype.html

halon博客 1176

LCZ数据下载及处理-以重庆市为例(完整Python代码)

LCZ数据下载及处理-以重庆市为例(完整Python代码)

WW、forever的博客 611

CKS-CN考试之路----02

其实我们根据题目也可以知道秘钥是叫clever-cactus。稍作等待后,确认pod的状态,如果是1/1基本就没问题了。这步不一定做.目的是确定秘钥的名字。

Q先生 654

【C#】ICloneable深复制与浅复制

【C#】ICloneable深复制与浅复制

wangnaisheng的专栏 594

YOLO26改进策略【YOLO和Mamba】| CVPR 2025:EfficientViM 压缩隐藏状态空间进行通道混合、单头设计减少内存操作,提升目标检测效率与精度

本文记录的是利用模块优化的目标检测网络模型。EfficientViM Block(基于隐藏状态混合器的状态空间对偶性模块) 的设计旨在,提升特征提取效率,同时兼顾全局依赖捕捉与局部细节保留。本文将深入研究的原理,并将其应用到中,通过重构特征提取流程、减少内存绑定操作、融合多阶段特征,增强模型在资源受限环境下的检测性能与速度。EfficientViM: Efficient Vision Mamba with Hidden State Mixer based State Space DualityEfficie

Limiiiing的博客 399

ICloneable接口的浅拷贝与深拷贝

ICloneable接口支持克隆,即用与现有实例相同的值创建类的新实例。ICloneable 接口包含一个成员 Clone,它用于支持除 MemberwiseClone (创建当前 Object的浅表副本)所提供的克隆之外的克隆。MSDN上给出MemberwiseClone方法的解释是MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该

17coding技术博客 1990

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

深拷贝、浅拷贝、ICloneable接口

使用微软企业库缓存,发现串缓存情况 因此需要封装一层,进行深拷贝之后再用,防止一个地方不小心修改了缓存的内容,其它地方受到影响 所有Model 继承ICloneable 实现深度拷贝 public object Clone { MemoryStream stream = new MemoryStream(); Binar

ISaiSai的专栏 776

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

ICloneable接口 Clone 深拷贝 浅拷贝

需要字段本身也实现了深拷贝Clone。应用场景不多,意义不大。 1. 隐含式地要求其子类和引用类也要实现ICloneable接口,如果引用层次比较深类似一个网状或树形接口,增加复杂性。 2. 考虑给sealed class实现ICloneable。 3. 值类型或者全都是简单值类型的引用对象用赋值可以应付大部分场景。 转载于:https://www.cnblogs.com/dir...

weixin_30747253的博客 197

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

.net平台下深拷贝和浅拷贝(实现ICloneable接口的基础上)

在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力。所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的。 基本概念: 浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个对象。大部分的引用类型,...

u012110480的专栏 733

[c#基础]ICloneable接口

摘要 该接口使你能够创建现有对象的副本的自定义的实现。该接口只提供了,一个Clone方法,实现对象的浅拷贝。有浅拷贝,那么就有相对应的深拷贝。但该接口并没有对我们提供,需要我们自己实现。 什么是浅拷贝与深拷贝? 浅拷贝 将对象的字段复制到新的对象副本中,同时将字段的值也复制过去,但引用类型值复制引用,而不是引用类型本身,也就是,如果源对象的引用类型的字段的值改变了,拷贝的对象的对应的引用类...

weixin_34209406的博客 775

实现ICloneable接口

问题有时需要创建一个自定义类型,它能为开发人员提供一种简单的机制来创建该类型实例的副本。解决方案实现System.ICloneable接口。原理如果我们有两个值类型的变量,将其中一个变量的值赋给另一个,实际上会创建该值的一个副本,这个副本与原来的值没有什么关系——这意味着改变其中一个的值不会影响另一个变量的值。而如果是两个引用类型的变量,其中一个变量的值赋给另一个的话(不包括str

瞎掰大数据-- 世界的本质是数据,胡侃瞎掰,专注微软大数据解决方案 1231

19、深拷贝与浅拷贝

深拷贝指的是创建一个对象的新实例,并递归地复制其所有字段的值,包括对象字段引用的其他对象,以确保新对象与原对象在内存中是完全独立的。

qq_27678663的博客 481

理解C#中对象的浅拷贝和深拷贝

本文章主要介绍C#中对象的拷贝,其中包括浅拷贝和深拷贝,以及浅拷贝和深拷贝的实现方式,不同的实现方式之间的性能对比。

风清扬的专栏 1737

ICloneable接口浅表副本和深层副本(备忘)

ICloneable接口使得实现该接口的类可以自定义Clone()方法,一般情况下,会调用Object类的MemberwiseClone()方法来实现克隆一个浅表副本。 按照MSDN的说法,所谓浅表副本就是生成一个和源对象相同的新对象,但是该对象中顶级(类的直接成员)成员实现拷

yuchang1980的专栏 620

C#实现对象的深拷贝与浅拷贝(正确打开方式)

首先吐槽一下部分优快云er,不要照抄,要有自己的思想,网上传的C#四种实现深拷贝的方法都属于比较偏的方法了,然而C#有内置的实现深拷贝和浅拷贝的方法,大家何必另辟蹊径,还全部都不加思索的就复制粘贴…… 1.实现默认的拷贝构造函数(复制构造函数) 这一部分请看官方文档: https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/how-to-write-a-copy-constructor

xy_learning的博客 2498

C#-深拷贝与浅拷贝

1.深拷贝与浅拷贝   拷贝即是通常所说的复制(Copy)或克隆(Clone),对象的拷贝也就是从现有对象复制一个“一模一样”的新对象出来。虽然都是复制对象,但是不同的 复制方法,复制出来的新对象却并非完全一模一样,对象内部存在着一些差异。通常的拷贝方法有两种,即深拷贝和浅拷贝,那二者之间有何区别呢?MSDN里对 IClone接口的Clone方法有这样的说明:在深层副本中,所有的对象都是重复的;...

LeePorter的博客 453

Item 27 避免使用ICloneable接口

  实现ICloneable接口,看起来是个不错的选择,想要类型支持拷贝,就实现ICloneable,不想支持拷贝,就不实现ICloneable。但是,大家仔细想一想,你的对象并不是在一个独立的环境中运行,需要考虑到对派生类的影响,基类已经实现了ICloneable接口,派生类也继承了基类的Clone方法,所以派生类最好也支持ICloneable接口,这样所有派生类都应保持一致,所以所有派生类都应...

weixin_30239339的博客 102

浅拷贝和深拷贝

有两种对象克隆的方法:浅拷贝和深拷贝。浅拷贝只是复制引用,而不会复制引用的对象。深拷贝会复制引用的对象。 因此,原始对象中的引用和浅拷贝对象中的同一个引用都指向同一个对象。而深拷贝的对象包含了对象的一切直接或间接的引用。参看维基百科(http://en.wikipedia.org/wiki/Object_copy)来获得更多解释。 ICloneable接口 ICloneable接口包含一

Rocky的博客 953
上一篇: 浅拷贝 深拷贝
下一篇: 用事务一次处理多条SQL语句
andycode
博客等级 码龄17年 12粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值