C#浅复制和深复制

来源:互联网 发布:java crontrigger 编辑:程序博客网 时间:2024/05/22 00:34

在C#编程当中,经常需要克隆一个对象,这是不可避免的遇到一个问题就是浅复制和深复制的问题

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;using System.Runtime.Serialization.Formatters.Binary;namespace ClonePragram{    class Program    {        static void Main(string[] args)        {            MyClass myClass1 = new MyClass(10,"joy",10);            /*1、myClass2和myClass1是同一个引用,指向同一个地址             *  结果:当myClass1属性改变,myClass2同样改变             */            MyClass myClass2 = myClass1;            /*2、这里使用MemberwiseClone(),返回一个浅表副本,称“浅复制”MSDN上的解释:该方法是创建一个新对象,             *  然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。             *  如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。             *  结果:myClass3复制了值类型myNum,但并没有复制引用的对象myNextClass,             *       当myClass1中值类型属性myNum改变,而myClass3中myNum没有改变;myClass3和myClass1中             *       引用类型属性myNextClass还是同一个引用,myClass1中myNextClass改变,myClass3也改变             */            MyClass myClass3 = (MyClass)myClass1.Clone();            /*3、“深复制”,在Clone2()方法中,创建一个新对象MyNextClass,myClass4和myClass1中引用类型属性             *   myNextClass不是同一个引用             */            MyClass myClass4 = (MyClass)myClass1.Clone2();            /*4、采用序列化和反序列化来“深复制”一个对象,首先将对象序列化到内存流中,             *  此时对象和对象引用的所用对象的状态都被保存到内存中,然后将内存流中的状态信息反序列化到一个新的对象中。             */            MyClass myClass5 = (MyClass)myClass1.Clone3();            Console.WriteLine("改变数值之前");            Console.WriteLine(string.Format("myClass1: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass1.myNum, myClass1.myNextClass.myNextNameProc, myClass1.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass2: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass2.myNum, myClass2.myNextClass.myNextNameProc, myClass2.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass3: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass3.myNum, myClass3.myNextClass.myNextNameProc, myClass3.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass4: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass4.myNum, myClass4.myNextClass.myNextNameProc, myClass4.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass5: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass5.myNum, myClass5.myNextClass.myNextNameProc, myClass5.myNextClass.myNextNumProc));            myClass1.myNum = 100;            myClass1.myNextClass.myNextNameProc = "Tom";            myClass1.myNextClass.myNextNumProc = 100;            Console.WriteLine("改变数值之后");            Console.WriteLine(string.Format("myClass1: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass1.myNum, myClass1.myNextClass.myNextNameProc, myClass1.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass2: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass2.myNum, myClass2.myNextClass.myNextNameProc, myClass2.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass3: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass3.myNum, myClass3.myNextClass.myNextNameProc, myClass3.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass4: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass4.myNum, myClass4.myNextClass.myNextNameProc, myClass4.myNextClass.myNextNumProc));            Console.WriteLine(string.Format("myClass5: [myNum] = {0},[myNextNameProc] = {1},[myNextNumProc] = {2}",                myClass5.myNum, myClass5.myNextClass.myNextNameProc, myClass5.myNextClass.myNextNumProc));            Console.ReadKey();        }    }    //标记可序列化    [Serializable]    public class MyClass : ICloneable    {        public int myNum;        public MyNextClass myNextClass = new MyNextClass();        public MyClass(int num,string childName,int childNum)        {            myNum = num;            myNextClass.myNextNameProc = childName;            myNextClass.myNextNumProc = childNum;        }        //2        public object Clone()        {            return this.MemberwiseClone();        }        //3        public object Clone2()        {            MyClass newMyClass = (MyClass)this.MemberwiseClone();            MyNextClass newChildClass = new MyNextClass();            newChildClass.myNextNameProc = this.myNextClass.myNextNameProc;            newChildClass.myNextNumProc = this.myNextClass.myNextNumProc;            newMyClass.myNextClass = newChildClass;            return newMyClass;        }        //4        public object Clone3()        {            MemoryStream stream = new MemoryStream();            BinaryFormatter formatter = new BinaryFormatter();            formatter.Serialize(stream, this);            stream.Position = 0;            return formatter.Deserialize(stream) as MyClass;        }    }    [Serializable]    public class MyNextClass    {        private string myNextName;        public string myNextNameProc { get { return myNextName; } set { myNextName = value; } }        public int myNextNumProc { get;set;}    }}

结果:


分析:Clone()是浅复制,Clone2()方法和Clone3()方法都是深复制,如果,对象中的引用属性太多,用Clone3()方法十分方便。

0 0
原创粉丝点击