




已阅读5页,还剩1页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C#编程之ICloneable 接口-c# 深复制与浅复制.txt骗子太多,傻子明显不够用了。我就是在路上斩棘杀龙游江过河攀上塔顶负责吻醒你的公主。支持克隆,即用与现有实例相同的值创建类的新实例。命名空间: 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 ErrorMessageprivate 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 : ICloneableprivate 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 : BaseTypeprivate 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 BaseTypeprivate 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, ICloneableprivate 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接口的派生类提供了必要
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025采购合同示范文本
- 合同范本模板哪里有
- 水塔上拆迁合同范本
- 2025新房购房合同范本新房买卖合同的合同范本
- 家电转卖维修合同范本
- 贵州茶叶合同范本
- 荒地补偿协议合同范本
- 瓦房扩建改造合同范本
- 出口长期供货合同范本
- 纸箱模具采购合同范本
- TB10104-2003 铁路工程水质分析规程
- 08J333 建筑防腐蚀构造
- DL∕ T 802.7-2010 电力电缆用导管技术条件 第7部分:非开挖用改性聚丙烯塑料电缆导管
- 突发环境事件应急预案编制要点及风险隐患排查重点课件
- 香港朗文1A-6B全部单词(音标版)
- CJJ57-2012 城乡规划工程地质勘察规范
- 入厂燃料验收管理验收统一标准
- 2024年03月新疆乌鲁木齐海关所属事业单位招考聘用14人笔试历年典型考题及考点研判与答案解析
- DZ∕T 0273-2015 地质资料汇交规范(正式版)
- 临沧市市级单位遴选(选调)笔试真题2021
- 肿瘤放射治疗质量控制规范
评论
0/150
提交评论