浅拷贝和深拷贝
2011-12-21 15:48 xiashengwang 阅读(347) 评论(0) 编辑 收藏 举报关于深拷贝和浅拷贝的区别,主要在对于引用类型的成员的拷贝上,浅拷贝只是简单的复制引用的地址,深拷贝会生成一个完全独立的对象,包括对象内的引用成员。
浅拷贝:Object类提供了一个MemberwiseClone方法,一般是基于它来实现。
深拷贝:要求对象要实现Serializable特性,表明它是可以被序列化的。利用对象的序列化和反序列化来实现深度拷贝。
完整的例子如下:
using System; using System.Collections.Generic; using System.Text; namespace CsharpBase { class CloneDemo { public static void Run() { People parent = new People("zhang", "30"); parent.type = "old"; parent.child.Name = "zhang xiao"; parent.child.Age = "1"; parent.PrintInfo(); //浅拷贝 People shallowParent = (People)parent.Clone(); //深拷贝 People deepParent = parent.DeepClone(); shallowParent.type = "shallow"; shallowParent.Name = "shallow zhang"; //浅拷贝对于引用型成员child只会复制其所在堆的首地址,不会进行真正的内容拷贝 //所以在这里shallowParent.child.Name的改变会导致parent.child.Name的改变,因为他们的 //child都指向了同一片内存区 shallowParent.child.Name = "shallow zhang xiao"; shallowParent.PrintInfo(); parent.PrintInfo(); deepParent.type = "Deep"; deepParent.Name = "Deep zhang"; //深拷贝能实现真正的拷贝 deepParent.child.Name = "Deep zhang xiao"; deepParent.PrintInfo(); parent.PrintInfo(); Console.ReadKey(); } [Serializable] private class People : ICloneable { public string type; public string Name; public string Age; public Child child = new Child(); public People(string name, string age) { Name = name; Age = age; } //浅拷贝 private People ShallowClone() { return (People)Clone(); } #region ICloneable public object Clone() { return this.MemberwiseClone(); } #endregion //深拷贝 public People DeepClone() { System.IO.Stream stream = new System.IO.MemoryStream(); System.Runtime.Serialization.IFormatter formater = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); formater.Serialize(stream, this); stream.Seek(0, System.IO.SeekOrigin.Begin); return (People)formater.Deserialize(stream); } public void PrintInfo() { System.Diagnostics.Debug.WriteLine("type:" + type); System.Diagnostics.Debug.WriteLine("parent:" + Name); System.Diagnostics.Debug.WriteLine("child:" + child.Name); System.Diagnostics.Debug.WriteLine("---------------"); } } [Serializable] private class Child { public string Name; public string Age; } } }
注意,Child类也必须有Serializable特性,否则formater.Serialize(stream, this);的时候会抛出SerializableException异常。
运行结果:
type:old parent:zhang child:zhang xiao --------------- type:shallow parent:shallow zhang child:shallow zhang xiao --------------- type:old parent:zhang child:shallow zhang xiao //这里被改变了 --------------- type:Deep parent:Deep zhang child:Deep zhang xiao --------------- type:old parent:zhang child:shallow zhang xiao //这里没变 ---------------