以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 Dot NET,C#,ASP,VB 』  (http://bbs.xml.org.cn/list.asp?boardid=43)
----  .NET对象克隆的深究  (http://bbs.xml.org.cn/dispbbs.asp?boardid=43&rootid=&id=11860)


--  作者:admin
--  发布时间:11/9/2004 2:26:00 AM

--  .NET对象克隆的深究


发信人: DRAGONESE (龙裔◎美丽的巴音布鲁克), 信区: DotNET
标  题: .NET对象克隆的深究
发信站: BBS 水木清华站 (Thu Aug 14 11:23:54 2003), 转信

关键字     .NET,VB.NET,克隆,CLONE  
   
出处     http://www.codeproject.com/useritems/Clone.asp
   


By Manoj G  

Posted 1 Aug 2003

Applied to:

VB.NET, XP, W2K, .NET 1.1, Win9X

摘要:本文讨论了为什么需要对象的克隆,怎样克隆以及对克隆的一些思考。

Download source files - 10 Kb  

简介
本文我将讨论.NET编程中一个比较感兴趣的方面——对象克隆。下面将讨论对象克隆的必要性、对象克隆的方法以及关于对象克隆的一些思考。
背景
大家一定知道.NET对象是有二大类型的:  值类型和引用类型。 值类型对象的变量表示对象本身,而且具有“copy-on-assignment”的行为。也就是说, 以下的讨论不适用于值类型。  
另一方面,引用类型的变量实际上是指向堆上的内存。 因此,如果你创建了一个引用类型的变量,并且将一个已存在的对象分配给它,实际上是创建了指向堆上的相同内存的另外一个对象。本文就是讨论这样的情况:创建的一个对象的新的拷贝,并且保存在一个变量中!  
为什么要克隆?
我认为当设置一个对象的状态要付出昂贵的代价,并且又需要取得该对象的一个拷贝以便改变当前的一些状态时,克隆就显得十分必要。下面列举一个刚好能体现我刚刚所说的情况的例子。 就拿 DataTable 类来说吧。建立一个 DataTable  
会包含诸如以下的操作:为取得架构和数据而查询数据库、添加约束、设置主键等等。那么,当需要该 DataTable 的一个新的拷贝,哪怕是对架构作极小的改变或添加新的一行记录等等, 明智的选择会是克隆已存在的对象再对其进行操作,而不是创建一个新的DataTable,  
那样将需要更多的时间和资源。  

克隆也广泛应用于数组和集合,这些时候往往会多次需要已存在对象的一个拷贝。  
克隆的类型
我们基于克隆的程度将克隆分成两大类:“深层”克隆和“浅表”克隆。“浅表”克隆得到一个新的实例,一个与原始对象类型相同、包含值类型字段的拷贝。但是,如果字段是引用类型的, 该引用将被拷贝, 而不是拷贝引用的对象。  
因此,原始对象的引用和克隆对象的引用都指向同一个对象。另一方面, 对象的“深层”克隆包含原始对象直接或间接引用的对象的所有拷贝。下面举例说明。

对象X引用对象A,对象A引用对象M。对象X的“浅表”克隆对象Y,同样也引用了对象A。相对比的是,对象X的“深层”克隆对象Y,却直接引用了对象B,并且间接引用对象N,这里,对象B是对象A的拷贝,对象N是对象M的拷贝。
实现克隆
System.Object提供了受保护的方法 MemberwiseClone,可用来实现“浅表”克隆。由于该方法标记为“受保护”级别,因此,我们只能在继承类或该类内部才能访问该方法。
.NET定义了一个IClonable接口,一个需要“深层”克隆而不是“浅表”克隆的类必须实现该接口。我们需要提供一个好的实现方法来达到该接口的Clone方法实现的功能。
有许多方法可以实现“深层”克隆。一个方法是将对象串行化到内存流中,然后反串行化到一个新的对象。我们将使用一个二进制(Binary)的 Formatter类或SOAP formatter类来进行深层串行化。做一个深写成连载长篇而刊登的 formatter 。 这个方法的问题是类和它的成员  
(完整的类表) 必须被标记为serializable,否则formatter会发生错误。  
反射是另外一个能达到相同目的的方法。 Amir Harel写的一篇好文章吸引了我, 他使用该方法提供一个好的克隆实现。 这篇文章讨论得非常好! 以下是链接:
http://www.codeproject.com/csharp/cloneimpl_class.asp

上面讨论的任何一个方法,都要求对象的成员类型能支持自我克隆,以确保“深层”克隆能成功进行。也就是说, 对象必须是可串行化的(serializable) ,或者每个独立的成员必须提供IClonable的实现。 如果不这样,我们根本不可能对对象进行“深层”克隆!
综述
克隆是提供给程序员的一个很好的方法。但是, 我们应该知道什么时候需要提供这样的功能,而且在某些情况下,严格地说,对象不应该提供这一个特性。 以SQLTransaction 类为例, 就不支持克隆。这一个类代表了SQL Server数据库的一个事务。  
克隆该对象没有任何意义,因为我们可能不能够理解一个数据库的一个活动的事务的克隆! 因此,如果你认为克隆对象的状态会产生应用程序逻辑上的矛盾,就不需要支持克隆。

  

                                                                                           (完)

  
  
  
--
            |                !!!            ___       
            |.===.        `  _ _  '        /\#/\           >X<
            {}o o{}      -  (0 0)  -      /(o o)\         (o o)
      ---ooO--(_)--Ooo--ooO--(_)--Ooo--ooO--(_)--Ooo--ooO--(_)--Ooo---
                                                      
<<< 欢迎访问.NET专题网站 DRAGONESE Studio.NET - http://DRAGONESE.dhs.org>>>


※ 修改:·DRAGONESE 于 Aug 14 11:26:37 修改本文·[FROM:  166.111.68.220]
※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.68.220]
上一篇
返回上一页
回到目录
回到页首



W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
62.500ms