Clone探讨 深度克隆-浅克隆-运算符赋值
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace CloneClass { class Program { static void Main(string[] args) { Results set1 = new Results(); Result result1 = new Result(); result1.ResultId = "1"; result1.ResultName = "lcc"; set1.ResultSetId = "Set1"; set1.result = result1; //运算符赋值 Results set2 = set1; //浅度克隆 Results set3 = (Results)set1.Clone(); //深度克隆 Results set4 = (Results)set1.DeepClone(); set1.ResultSetId = "Set2"; set1.result.ResultName = "Shikyoh"; Console.WriteLine("运算符赋值 结果"); Console.WriteLine(set2.ResultSetId + "," + set2.result.ResultId + "," + set2.result.ResultName); Console.WriteLine("浅度克隆 结果"); Console.WriteLine(set3.ResultSetId + "," + set3.result.ResultId + "," + set3.result.ResultName); Console.WriteLine("深度克隆 结果"); Console.WriteLine(set4.ResultSetId + "," + set4.result.ResultId + "," + set4.result.ResultName); Console.ReadLine(); } } [Serializable] public class Result { public string ResultId; public string ResultName; } [Serializable] public class Results { public string ResultSetId; public Result result; public object Clone() { return this.MemberwiseClone(); } public object DeepClone() { MemoryStream steam = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(steam, this); steam.Position = 0; return formatter.Deserialize(steam); } } }
结果:
运算符操作 简单的引用类型的一个复制。还是指向同一地址。
浅克隆 只能克隆本类之中的成员
深度克隆 全部克隆,完全实现克隆的效果。
参考:
MemberwiseClone 方法创建一个浅表副本,具体来说就是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。
为了实现深度复制,我们就必须遍历有相互引用的对象构成的图,并需要处理其中的循环引用结构。这无疑是十分复杂的。幸好借助.Net的序列化和反序列化机制,可以十分简单的深度Clone一个对象。原理很简单,首先将对象序列化到内存流中,此时对象和对象引用的所用对象的状态都被保存到内存中。.Net的序列化机制会自动处理循环引用的情况。然后将内存流中的状态信息反序列化到一个新的对象中。这样一个对象的深度复制就完成了。在原型设计模式中CLONE技术非常关键。