现在的位置: 首页 > 综合 > 正文

Copy & Clone

2013年01月19日 ⁄ 综合 ⁄ 共 1096字 ⁄ 字号 评论关闭

最近在写SqlCenter的测试的时候,经常要写Clone和Copy的测试。由于这个需要,好好的温习了下Clone(Shallow Copy)和 Copy(Deep Copy).

我们知道:

             Clone,浅拷贝,它的实现就是把要拷贝的对象的值,一一的赋值给要拷贝的对象。这里要注意:一一赋值。如果是堆对象,其实就是类似于C语言中的指针拷贝。

            Copy,深拷贝,它的实现是把自己拥有的东西,重新Create一份,交给要Copy的对象。这样它们就具有了2份一样的财富。 彼此之间除了量上相等意外,没有其他联系。

下面用拙图表达下思想,也试试LiveWriter上传图片的效果 :)

红色为原对象,蓝色为Clone而来的对象。其中假设1代表栈对象,obj代表堆对象。

/// B = A.Clone();

Clone时发生的内存复制,下图是现在的一个内存分配图,我们可以看到堆对象(A.obj与B.obj)同时指向Object对象。

经常,我们要测试对象当object变化时,是否对A与B的影响,也就是Clone是否成功。于是

我们有这样的断言:

//change the object value

Assert.AreEqual(A.obj,B.obj);

这两天由于没有很好理解这一过程,经常写下这样的代码:

B.obj = new Objct();

Assert.AreEqual(A.obj,B.obj);

当然总是不能通过。从下图,我们可以很好看出,其实内存中,B.obj 和A.obj已经不再指向同一块内存了。

但有时总是错误的认为,A.obj和B.obj指向同一内存,改变B.obj,A.obj也一定同时改变。错误犯得很丑!:(

 

对于深度复制:

深度Copy,它把资源也赋值一次,使对象拥有不同的资源,但资源的内容是一样的。对于堆资源来说,就是在开辟一片堆内存,把原来的内容拷贝。正如上图中Obj和NewObj,它们具有相同内容。

当然深度复制也存在一定复制深度问题,如果Obj中还有堆资源,那么是否再次进行深度Copy,就要就情况决定了。

对于一个类Copy方式的测试而言,进行如下测试必不可少的:

Assert.AreEqual(A,B);

Assert.AreEqual(A.obj,B.obj);

Assert.AreEqual(A.obj.field,B.obj.field)

.....

至此,我懂得也表达差不多了。以前一直认为自己对深/浅拷贝是有认识的。经过最近的实践,才发现将理论用于实践,或者再实践中去检测理论,且非刻意而为,真是件难事!

其实深浅拷贝问题,在很多模式中都有体现,等有空好好学习下:)

抱歉!评论已关闭.