简介:this
System.Object 几乎是全部的类、结构、委托类型的基类。System.Object有一个MemberwiseClone 的方法来帮助咱们建立一个当前对象的实例。spa
存在的问题:code
System.Object 提供的MemberwiseClone 方法只是对象的浅拷贝,只能把当前对象的非静态字段拷贝到新对象。若是属性是值类型,那么就把值拷贝一份,若是是引用类型,那么只拷贝对原对象的引用。这就意味着MemberwiseClone 不可以建立对象的深拷贝。orm
解决方案:对象
有不少实现深拷贝的方式,在这里我只介绍其中的2种。blog
1.经过序列化和反序列化实现深拷贝。接口
2.经过反射来实现深拷贝。get
今天我就先介绍第一种:序列化和反序列化实现深拷贝。string
ICloneable 接口提供给咱们一个能够自定义实现拷贝的Clone方法。it
序列化就是把对象转换成字节流的过程,反序列化相反,就是把字节流转换成原对象的过程。在.NET中有不少序列化的方式,好比二进制序列化、XML序列化等等。二进制序列化要比XML序列化快得多。因此二进制序列化是比较好的序列化和反序列化。
经过序列化和反序列化,可以实现对一个对象的深拷贝,可是前提是须要序列化和反序列化的类都要标记为serializable特性。
下面的例子,我建立一个职员类,拥有一个部门属性。
1 [Serializable] 2 public class Department 3 { 4 public int DepartmentId { get; set; } 5 public string DepartmentName { get; set; } 6 }
1 [Serializable] 2 public class Employee : ICloneable 3 { 4 public int EmployeeId { get; set; } 5 public string EmployeeName { get; set; } 6 public Department Department { get; set; } 7 8 public object Clone() 9 { 10 using (MemoryStream stream = new MemoryStream()) 11 { 12 if (this.GetType().IsSerializable) 13 { 14 BinaryFormatter formatter = new BinaryFormatter(); 15 formatter.Serialize(stream, this); 16 stream.Position = 0; 17 return formatter.Deserialize(stream); 18 } 19 return null; 20 } 21 } 22 }
看到咱们用二进制序列化和反序列化实现了IClone接口的Clone方法。这个Clone方法咱们能够提出来做为一个扩展方法:
1 public static class ObjectExtension 2 { 3 public static T CopyObject<T>(this object objSource) 4 { 5 using (MemoryStream stream = new MemoryStream()) 6 { 7 BinaryFormatter formatter = new BinaryFormatter(); 8 formatter.Serialize(stream, objSource); 9 stream.Position = 0; 10 return (T)formatter.Deserialize(stream); 11 } 12 } 13 }
看源代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 using System.Runtime.Serialization.Formatters.Binary; 7 8 namespace SerializeCopy 9 { 10 [Serializable] 11 public class Department 12 { 13 public int DepartmentId { get; set; } 14 15 public string DepartmentName { get; set; } 16 } 17 18 [Serializable] 19 public class Employee : ICloneable 20 { 21 public int EmployeeId { get; set; } 22 public string EmployeeName { get; set; } 23 public Department Department { get; set; } 24 25 public Object Clone() 26 { 27 28 return ObjectExtension.CopyObject<Employee>(this); 29 } 30 31 } 32 public static class ObjectExtension 33 { 34 35 public static T CopyObject<T>(this object objsource) 36 { 37 using (MemoryStream stream = new MemoryStream()) 38 { 39 BinaryFormatter formatter = new BinaryFormatter(); 40 41 formatter.Serialize(stream, objsource); 42 stream.Position = 0; 43 44 return (T)formatter.Deserialize(stream); 45 46 } 47 48 } 49 50 } 51 52 }
调用代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace SerializeCopy 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Employee emp = new Employee(); 13 14 emp.EmployeeId = 1000; 15 emp.EmployeeName = "IT少年"; 16 emp.Department = new Department { DepartmentId = 1, DepartmentName = "Examination" }; 17 18 Employee empclone = emp.Clone() as Employee; 19 20 emp.EmployeeId = 1003; 21 emp.EmployeeName = "TTT"; 22 emp.Department.DepartmentId = 3; 23 emp.Department.DepartmentName = "admin"; 24 Console.WriteLine("----emp原始对象------"); 25 Console.WriteLine("拷贝前DepartmentName应该是admin: " + emp.Department.DepartmentName); 26 Console.WriteLine("拷贝前DepartmentID应该是3: " + emp.Department.DepartmentId); 27 28 Console.WriteLine("----empclone拷贝对象------"); 29 Console.WriteLine("拷贝DepartmentName应该是Examination: " + empclone.Department.DepartmentName); 30 Console.WriteLine("拷贝DepartmentID应该是1: " + empclone.Department.DepartmentId); 31 Console.ReadKey(); 32 } 33 } 34 }
调用结果:
须要注意的一点是,用序列化和反序列化深拷贝,须要将须要拷贝的属性标记为Serializable