大多数稍微有过一些编程实践的C#初学者都应该听说过“浅层复制”和“深层复制”的区别,如果尚不清楚的盆友还是先去搜索一下相关的专题,我在这里不多说,本文主要内容是记录一下区别于前两者的另外一种在有较复杂的类层次情况下的复制方式。
比如有如下类的声明:(代码1)
public class ClassOne
{
public int Value = 0;
}
public class ClassTwo : ICloneable
{
private ClassOne inner = new ClassOne();
public object Clone()
{
return this.MemberwiseClone();
}
}
即第二个类将第一个类作为私有成员进行封装。此时若直接调用ClassTwo对象的Clone()方法则实际上是进行了ClassTwo的浅层复制。
如果想通过Clone()方法进行深层复制,则需要进行如下修改:(代码2)
public class ClassOne
{
public int Value = 0;
}
public class ClassTwo : ICloneable
{
private ClassOne one = new ClassOne();
public object Clone()
{
ClassTwo clone = (ClassTwo)this.MemberwiseClone();
clone.one = new ClassOne();
clone.one.Value = this.one.Value;
return clone;
}
}
写到这里这两个类的确已经相安无事了。然而事情没这么简单,接下来如果从ClassTwo派生出一个子类ClassThree如下:(代码3)
public class ClassThree : ClassTwo
{
public readonly int Key = 100;
private ClassOne two = new ClassOne();
...
}
此时如果想要通过Clone()对ClassThree进行深层复制该如何做呢?有些和我之前一样小白的盆友们会立刻想到如下修改该方式:(代码4)
public class ClassThree : ClassTwo, ICloneable
{
public readonly int Key = 100;
private ClassOne two = new ClassOne();
public new object Clone()
{
ClassThree clone = (ClassThree)this.MemberwiseClone();
clone.two = new ClassOne();
clone.two.Value = this.two.Value;
return clone;
}
}
稍微有些经验的盆友马上就会发现,这样的修改并不能正确的实现深层复制的目的,因为ClassTwo中的成员ClassTwo.one是private的,无法直接访问,而this.MemberwiseClone()方法只会将其进行浅层复制。
于是马上就能想到的另一种修改方法如下:(代码5)
public class ClassThree : ClassTwo, ICloneable
{
public readonly int Key = 100;
private ClassOne two = new ClassOne();
public new object Clone()
{
ClassThree clone = (ClassThree)base.Clone();
clone.Key = this.Key;
clone.two = new ClassOne();
clone.two.Value = this.two.Value;
return clone;
}
}
看似完成了需求,但实际上这次的修改根本无法便已成功,原因出在第9行代码,因为ClassThree.Key是只读的,无法在构造函数以外的方法中对齐进行赋值。
代码4和代码5的思路都不对,岂不是进入死胡同了?其实不然,经过我的简单试验发现只要删除代码4中的第9行就可以完美的实现我们的深层复制需求,完整代码如下:(代码6)
public class ClassOne
{
public int Value = 0;
}
public class ClassTwo : ICloneable
{
private ClassOne one = new ClassOne();
public object Clone()
{
ClassTwo clone = (ClassTwo)this.MemberwiseClone();
clone.one = new ClassOne();
clone.one.Value = this.one.Value;
return clone;
}
}
public class ClassThree : ClassTwo, ICloneable
{
public readonly int Key = 100;
private ClassOne two = new ClassOne();
public new object Clone()
{
ClassThree clone = (ClassThree)base.Clone();
clone.two = new ClassOne();
clone.two.Value = this.two.Value;
return clone;
}
}
其实原因很简单,在执行代码6中第26行时,.NET框架首先执行了其父类的Clone()方法,在本例中则是实现了对父类的深层复制,接下来是隐式的对当前类中的除父类中以外的非静态成员进行了浅层复制,即.NET框架已经悄悄的帮我们完成了clone.Key = this.Key的操作,真相大白,功德圆满。
总结,在执行base.Clone()的实际操作可分解为:首先执行了其父类的Clone()方法,然后隐式的对当前类中的除父类中以外的非静态成员进行了浅层复制,最后返回类型与this相同的经过链式复制新对象。
作者:KeViNOne
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接及作者主页链接,否则保留追究法律责任的权利。
分享到:
相关推荐
C#中Clone一个对象的值到另一个对象案例 c#经典案例.pdf
详细的描述了Java中 clone方法使用
Java中clone方法共6页.pdf.zip
主要介绍了JQuery中clone方法复制节点,实例分析了clone方法浅克隆与深克隆的使用方法,需要的朋友可以参考下
Java中的clone方法详解_动力节点Java学院,动力节点口口相传的Java黄埔军校
List的深度复制 浅谈C#中List<T>对象的深度拷贝问题
clone顾名思义是复制, 在Java语言中, clone方法被对象调用,所以会复制对象。所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象。那么在java语言中,有几种方式可以创建...
一、List对象中的T是值类型的情况(int 类型等)...1、对于引用类型的List无法用以上方法进行复制,只会复制List中对象的引用,可以用以下扩展方法复制: static class Extensions { public static IList<T> Clone(t
主要介绍了Java 数组复制clone方法实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Object类中的clone方法clone()方法的作用克隆方法用于创建对象的拷贝,为了使用clone方法,类必须实现java.lang.Cloneable接口
clone的用法 希望有帮助,仅供参考 通过例子的分析,可以对克隆的方法有所深入了解
Java Clone(类的复制)实例代码 Java Clone(类的复制)实例代码
在使用高版本版KEIL时,提示要升级固件,升级后就出现JLINK is Clone的提示!“the emulator is JLink-Clone, the segger software only support orginal segger device” 然后闪退,IDE崩溃关闭! 解决方案: 1....
clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象。下面通过本文给大家介绍java中的clone方法,感兴趣的朋友一起看看吧
jquery.clone
下面小编就为大家带来一篇C# 使用反射来实现对象的深度复制方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Java的clone方法[归类].pdf
JavaScript中并没有直接提供对象复制(Object Clone)的方法。因此下面的代码中改变对象b的时候,也就改变了对象a。 a = {k1:1, k2:2, k3:3}; b = a; b.k2 = 4; 如果只想改变b而保持a不变,就需要对对象a进行复制。 ...
给大家介绍了jQuery中clone()函数实现表单中增加和减少输入项的实例代码,非常不错,具有参考借鉴价值,需要的朋友参考下吧