大多数稍微有过一些编程实践的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 方法来复制一个对象的值到另一个对象。 什么是 Clone? Clone 是一种复制对象的方法,它可以将一个对象的值复制到另一个对象中。 Clone 方法可以分为浅复制和深...
要实现图像的复制,我们可以利用Clone()方法。Clone()方法创建一个与现有图像具有相同内容和大小的新图像。例如: ```csharp Bitmap originalImage = (Bitmap)Image.FromFile("path_to_image.jpg"); Bitmap ...
为了实现深拷贝,通常需要在自定义类中重写`clone()`方法,并且确保所有的引用字段也被正确复制。 4. **安全性与并发考虑**: - `clone()`方法不会调用构造函数,因此不能用于初始化新对象。此外,在多线程环境中...
以下是对`ClassB`类中的浅复制实现的分析: ```csharp public class ClassB : ICloneable { public ClassA Member = new ClassA(); public object Clone() { // 这里原本应该返回的是一个浅复制的结果 // ...
本文将深入探讨这两种拷贝方式以及它们在C#中的实现方法,特别是如何使用`MemberwiseClone`、反射以及反序列化技术。 首先,浅拷贝是通过`Object.MemberwiseClone()`方法来实现的。这个方法为对象创建一个新的实例...
详细的描述了Java中 clone方法使用
本主题将深入探讨C#中的复制概念,特别是通过`Copy`方法实现的浅复制和深复制。 首先,我们要理解什么是复制。复制一个对象意味着创建一个新的对象,它的属性值与原始对象相同。根据复制方式的不同,可以分为浅复制...
一、List对象中的T是值类型的情况(int 类型等)...1、对于引用类型的List无法用以上方法进行复制,只会复制List中对象的引用,可以用以下扩展方法复制: static class Extensions { public static IList<T> Clone(t
下面我们将详细探讨这两种复制方法以及如何在C#中实现它们。 首先,浅表复制是通过`ICloneable`接口来实现的。在示例代码中,`Person`类实现了`ICloneable`接口,并提供了`Clone()`方法,该方法通过调用`...
JQuery库中的clone方法是其强大的功能之一,它允许开发者复制文档中的元素节点,进而可以将这些副本插入到DOM的其他位置或进行其他操作。在本知识点中,我们将详细介绍JQuery中clone方法复制节点的使用方法,重点...
在C#中,图像处理主要通过System.Drawing命名空间下的类来实现。例如,Bitmap类用于表示位图图像,Graphics类用于绘制和操作图像,Image类是所有图像类型的基础类。常见的图像处理操作包括: 1. **加载与保存图像**...
在C#中,可以使用Bitmap对象的Clone方法创建一个新的Bitmap实例,然后设置新的尺寸。例如: ```csharp int newWidth = 800; // 新的宽度 int newHeight = (int)(bitmap.Height * (newWidth / (double)bitmap....
### C#中的浅拷贝与深拷贝 在C#编程语言中,对象的复制是一项基本而重要的操作。根据复制的方式不同,可以分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。这两种复制方式各有其特点和适用场景。 #### 值类型...
在IT行业中,C#是一种广泛使用的编程语言,尤其在开发Windows桌面应用和游戏时。Bitmap是.NET Framework中处理图像的核心类,它允许开发者对图像进行各种操作,如加载、保存、绘制、裁剪等。本篇文章将深入探讨如何...
在C#中,可以借助AForge.NET或者OpenCV.NET等第三方库来访问和控制摄像头。例如,AForge.NET提供了VideoCaptureDevice类,用于捕获来自摄像头的视频流。通过创建该类的实例,设置帧率、分辨率等参数,然后调用Start...
例如,如果`CloneClass`有一个`UnCloneA`类型的成员变量,为了实现深克隆,我们需要在`clone`方法中对`UnCloneA`对象进行复制: ```java @Override protected Object clone() throws CloneNotSupportedException { ...
总结起来,Java中数组复制的`clone()`方法适用于基本类型的数组,可以实现完全独立的副本。但对于对象数组,`clone()`仅创建浅拷贝,仅复制数组引用,不复制对象。因此,在处理对象数组时,需要根据具体需求决定是否...
Java中的clone方法详解_动力节点Java学院,动力节点口口相传的Java黄埔军校
Java的`clone()`方法在软件开发中扮演着重要的角色,特别是在需要复制对象的场景下。在Java中,对象的复制并非像C++等语言中的指针复制那样简单,因为Java中没有指针的概念,而是使用引用。这导致了在默认情况下,...