C#编程之ICloneable 接口--c# 深复制与浅复制.doc
上传人:qw****27 上传时间:2024-09-12 格式:DOC 页数:6 大小:31KB 金币:15 举报 版权申诉
预览加载中,请您耐心等待几秒...

C#编程之ICloneable 接口--c# 深复制与浅复制.doc

C#编程之ICloneable接口--c#深复制与浅复制.doc

预览

在线预览结束,喜欢就下载吧,查找使用更方便

15 金币

下载此文档

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

C#编程之ICloneable接口--c#深复制与浅复制.txt骗子太多,傻子明显不够用了。我就是在路上斩棘杀龙游江过河攀上塔顶负责吻醒你的公主。支持克隆,即用与现有实例相同的值创建类的新实例。命名空间:System程序集:mscorlib(在mscorlib.dll中)语法C#[ComVisibleAttribute(true)]publicinterfaceICloneableICloneable接口包含一个成员Clone,它用于支持除MemberwiseClone所提供的克隆之外的克隆。语法C#ObjectClone()Clone既可作为深层副本实现,也可作为浅表副本实现。在深层副本中,所有的对象都是重复的;而在浅表副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。结果克隆必须与原始实例具有相同的类型或是原始实例的兼容类型。ICloneable听起来是个好主意:可以为那些支持复制的类型实现ICloneable接口。如果不想支持复制,那就不要实现它。但是我们的类型并非活在真空中。让一个类型支持ICloneable接口会影响它的派生类。一旦类型支持ICloneable接口,那么它所有的派生类也都必须支持它。而且,其所有成员类型也都要支持ICloneable接口,或者有其他创建复制的机制。最后,当我们设计的类型包含交织成网状的对象时,支持深复制将变得很困难。ICloneable接口在其官方的定义里很巧妙地绕过了这个问题,其定义如下:ICloneable接口或者支持深复制(deepcopy),或者支持浅复制(shallowcopy)。浅复制指的是新对象包含所有成员变量的副本,如果成员变量为引用类型,那么新对象将和原对象引用同样的对象。深复制指的也是新对象包含所有成员变量的副本,但是所有引用类型的成员变量将被递归地克隆。对于C#的内建类型,例如整数,深复制和浅复制产生的是同样的结果。那么我们的类型应该支持哪一个?这要根据具体类型而定。但是在同一个对象中混合浅复制和深复制会导致许多不一致的问题。当涉足ICloneable接口时,这样的问题很难逃脱。大多数情况下,避免ICloneable接口反倒会获得一个比较简单的类——对类的客户来讲比较容易使用,对创建者来讲也比较容易实现。任何只包含内建类型成员的值类型都不需要支持ICloneable接口;一个简单的赋值语句对struct的值所做的复制要比Clone()来得高效得多。Clone()必须对返回值进行装箱,才能转换为一个System.Object引用。调用者则必须进行强制转型才能获取真正的值。值类型默认的复制支持对我们来说已经足够了。我们没有必要再编写Clone()函数来重复这项工作。如果值类型中包含引用类型呢?最明显的例子是包含字符串:publicstructErrorMessage{privateinterrCode;privateintdetails;privatestringmsg;//忽略细节。}字符串是一个特殊的例子,因为string是一个具有常量性的类。如果我们对ErrorMessage对象进行赋值,两个ErrorMessage对象都将引用同一个字符串。但这并不会导致任何问题,而这放到一个普通的引用类型就会出现问题。通过任何一个对象更改msg变量,都会创建一个新的string对象(参见条款7)。更一般的情况——创建一个包含任意引用类型变量的struct——就比较复杂了。不过这种情况相当少见。C#语言为struct提供的内建赋值操作创建的是一个浅复制——即两个struct引用的是同一个引用类型对象。要创建一个深复制,我们需要克隆其内包含的引用类型,而且需要确知其Clone()方法支持深复制。无论哪种情况,我们都没有必要为值类型添加ICloneable接口支持——赋值操作符可以创建任何值类型的新副本。综上所述,对值类型来讲,提供ICloneable接口的理由不够充分。下面我们来看引用类型。引用类型要通过支持ICloneable接口来表明自身支持浅复制或者深复制。但是在为一个类添加ICloneable接口支持时,我们要审慎行事,因为那样做会强制要求该类的所有派生类也都必须支持ICloneable接口。考虑下面两个类:classBaseType:ICloneable{privatestring_label="classname";privateint[]_values=newint[10];publicobjectClone(){BaseTyperVal=newBaseType();条款27:避免ICloneable接口154rVal._label=_lab