您的位置:首页 > 编程语言 > C#

C#读书笔记----浅度复制与深度复制

2011-07-20 22:32 267 查看
前提条件:从 一个变量到另一个变量按值复制对象,而不是按引用复制对象(即以与结构相同的方式复制)可能非常复杂。因为一个对象可能包含许多对象的引用,例如字段、成 员等,这将涉及许多烦人的处理操作。把每个成员从一个对象复制到另一个对象中可能不会成功,因为其中一些成员可能是引用类型。
浅复制:简单地按照成员复制对象可以通过派生于System.Object的MemberwiseClone()方法来完成,这是一个受保护的方法,但是很容易在对象上定义一个调用该方法的公共方法。这个方法的复制功能成为浅复制。
浅复制的好处:不用引用对象类型。
浅复制的方法:
01	using System;
02	using System.Collections.Generic;
03	using System.Text;
04
05	namespace ConsoleApplication2
06	{
07	    public class Content
08	    {
09	        public int Val;
10	    }
11
12	    public class Cloner
13	    {
14	        public Content MyContent = new Content();
15	        public Cloner(int newVal)
16	        {
17	            MyContent.Val = newVal;
18	        }
19	        public object GetCopy()
20	        {
21	            return MemberwiseClone();
22	        }
23	    }
24
25	    public class Program
26	    {
27	        static void Main(string[] args)
28	        {
29	            Cloner mySource = new Cloner(5);
30	            Cloner myTarget = (Cloner)mySource.GetCopy();
31	            Console.WriteLine("MyTarget.MyContent.val = {0}",myTarget.MyContent.Val);
32	            mySource.MyContent.Val = 2;
33	            Console.WriteLine("MyTarget.MyContent.val = {0}", myTarget.MyContent.Val);
34	            Console.ReadKey();
35	        }
36	    }
37	}


这里的mySource.MyContent.Val = 2改变了该公共字段val的值,所以导致了生成结果如下:

MyTarget.MyContent.val = 5

MyTarget.MyContent.val = 2

上面通过复制引用类型来体现了浅度复制的使用方法。

如果想要使生成的值都为5,就需要使用深度复制.
关于深度复制:
使用深度复制,必须使类实现ICloneable接口,该接口有一个方法Clone(),这个方法不带参数,返回一个对象类型, 其签名和上面使用的GetCopy()方法相同。

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace ConsoleApplication2
6 {
7     public class Content
8     {
9         public int Val;
10
11     }
12
13     public class Cloner:ICloneable
14     {
15         public Content MyContent = new Content();
16
17         public Cloner(int newVal)
18         {
19             MyContent.Val = newVal;
20         }
21         public object GetCopy()
22         {
23             return MemberwiseClone();
24         }
25
26         #region ICloneable 成员
27
28         public object Clone()
29         {
30             Cloner clonedCloner = new Cloner(MyContent.Val);
31             return clonedCloner;
32         }
33
34         #endregion
35     }
36
37     public class Program
38     {
39         static void Main(string[] args)
40         {
41             Cloner mySource = new Cloner(5);
42             Cloner myTarget = (Cloner)mySource.Clone();
43             Console.WriteLine("MyTarget.MyContent.val = {0}",myTarget.MyContent.Val);
44             mySource.MyContent.Val = 2;
45             Console.WriteLine("MyTarget.MyContent.val = {0}", myTarget.MyContent.Val);
46             Console.ReadKey();
47         }
48     }
49 }


因为在将Cloner实现ICloneable时使用了深度复制,来创建了作为当前实例(这里指clonedCloner)副本的新对象,
最后在测试深度复制时,又调用了Clone()的方法,而没有调用GetCopy()方法,所以导致了myTarget.MyContent.Val的值一直是new Cloner(5),而不是在最后定义的值2.
经过这个知识点的学习,我认为ICloneable()接口的存在就是为了调用clone()方法的,如果需要将某个引用类型或者值类型的值直接复制给对象,
就直接让其实现该接口的方法,这个可能理解的不正确,希望大家和我交流。

关于ICloneable()接口的Clone()方法的说明:
Clone 既可作为深层副本实现,也可作为浅表副本实现。在深层副本中,所有的对象都是重复的;而在浅表副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。

结果克隆必须与原始实例具有相同的类型或是原始实例的兼容类型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: