首页 / C# / C# 浅拷贝和深拷贝的实现
C# 浅拷贝和深拷贝的实现
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C# 浅拷贝和深拷贝的实现,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5602字,纯文字阅读大概需要9分钟。
内容图文
拷贝(复制)为对象创建副本,即将对象中的所有字段复制到新的对象(副本中)。拷贝有两种:浅拷贝和深拷贝,微软建议用类型继承ICloneable接口的方式明确该类型是可以被拷贝的,ICloneable接口只提供了一个Clone方法,需要根据需要在Clone方法内实现浅拷贝或深拷贝。
1、浅拷贝:把源对象中的值类型字段的值和引用类型字段的引用复制到副本中。在源对象(副本)中,修改值类型字段的值不会影响到副本(源对象),而修改引用类型字段的值会影响到副本(源对象)。
注意:string类型除外,虽然string类型是引用类型,但是由于该引用类型的特殊性,在浅拷贝过程,副本中会创建新的字符串并把对应的值复制过来,字符串应被看成值类型。
浅拷贝声明代码,使用Object.MeberwiseClone方法进行浅拷贝:
1 class Employee : ICloneable 2 { 3 public string ID { get; set; } 4 public int Age { get; set; } 5 public Department DepartmentName { get; set; } 6 7 //实现ICloneable接口的Clone方法 8 public object Clone() 9 { 10 return this.MemberwiseClone();//浅拷贝 11 } 12 } 13 class Department 14 { 15 public string DepartmentName { get; set; } 16 public Department(string value) 17 { 18 DepartmentName = value; 19 } 20 public override string ToString() 21 { 22 return DepartmentName.ToString(); 23 } 24 }
调用浅拷贝代码:
1 Employee emp1 = new Employee() 2 { 3 ID = "NO1", 4 Age = 20, 5 DepartmentName = new Department("Technology") 6 }; 7 Employee emp2 = emp1.Clone() as Employee;//浅拷贝 8 9 Console.WriteLine("-------初始化赋值------"); 10 Console.WriteLine(string.Format("[emp1] id:{0}\tage:{1}\tdepartment:{2}", emp1.ID, emp1.Age, emp1.DepartmentName)); 11 Console.WriteLine(string.Format("[emp2] id:{0}\tage:{1}\tdepartment:{2}", emp2.ID, emp2.Age, emp2.DepartmentName)); 12 13 Console.WriteLine("\n-------改变emp1的值-------"); 14 emp1.ID = "NO2"; 15 emp1.Age = 22; 16 emp1.DepartmentName.DepartmentName = "sales"; 17 Console.WriteLine(string.Format("[emp1] id:{0}\tage:{1}\tdepartment:{2}", emp1.ID, emp1.Age, emp1.DepartmentName)); 18 Console.WriteLine(string.Format("[emp2] id:{0}\tage:{1}\tdepartment:{2}", emp2.ID, emp2.Age, emp2.DepartmentName)); 19 20 Console.WriteLine("\n-------改变emp2的值-------"); 21 emp2.ID = "NO3"; 22 emp2.Age = 24; 23 emp2.DepartmentName.DepartmentName = "personnel"; 24 Console.WriteLine(string.Format("[emp1] id:{0}\tage:{1}\tdepartment:{2}", emp1.ID, emp1.Age, emp1.DepartmentName)); 25 Console.WriteLine(string.Format("[emp2] id:{0}\tage:{1}\tdepartment:{2}", emp2.ID, emp2.Age, emp2.DepartmentName));
运行结果:
-------初始化赋值------ [emp1] id:NO1 age:20 department:Technology [emp2] id:NO1 age:20 department:Technology -------改变emp1的值------- [emp1] id:NO2 age:22 department:sales [emp2] id:NO1 age:20 department:sales -------改变emp2的值------- [emp1] id:NO2 age:22 department:personnel [emp2] id:NO3 age:24 department:personnel
从结果可以看出,Age是值类型,ID是string类型这里被当做值类型处理,所以ID和Age修改了对另一个对象没有影响;Department属性是引用类型,浅拷贝emp1和emp2引用的是同一个Department对象,其中一个修改了DepartmentName的值会影响另一个。
2、深拷贝:把源对象的值类型字段和引用类型字段,重新创建并赋值。在源对象(副本)中,修改值类型字段的值或者引用类型字段的值都不会影响到副本(源对象)。
建议使用序列化的形式来进行深拷贝
深拷贝代码:
[Serializable]//标记可序列化 class Employee : ICloneable { public string ID { get; set; } public int Age { get; set; } public Department DepartmentName { get; set; } //实现ICloneable接口的Clone方法 public object Clone() { using (MemoryStream stream = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Seek(0, SeekOrigin.Begin); return formatter.Deserialize(stream) as Employee; } } } [Serializable]//标记可序列化 class Department { public string DepartmentName { get; set; } public Department(string value) { DepartmentName = value; } public override string ToString() { return DepartmentName.ToString(); } }
跟上面调用浅拷贝代码一样调用深拷贝,运行结果:
-------初始化赋值------ [emp1] id:NO1 age:20 department:Technology [emp2] id:NO1 age:20 department:Technology -------改变emp1的值------- [emp1] id:NO2 age:22 department:sales [emp2] id:NO1 age:20 department:Technology -------改变emp2的值------- [emp1] id:NO2 age:22 department:sales [emp2] id:NO3 age:24 department:personnel
拷贝以后,无论是修改值类型还是引用类型,都对另一个对象没有影响。
3、要同时实现深拷贝和浅拷贝,可以在Clone方法外,额外实现两个方法,声明为DeepClone和Shallow:
1 [Serializable]//标记可序列化 2 class Employee : ICloneable 3 { 4 public string ID { get; set; } 5 public int Age { get; set; } 6 public Department DepartmentName { get; set; } 7 8 //实现ICloneable接口的Clone方法 9 public object Clone() 10 { 11 return this.MemberwiseClone(); 12 } 13 14 //深拷贝 15 public Employee DeepClone() 16 { 17 using (MemoryStream stream = new MemoryStream()) 18 { 19 BinaryFormatter formatter = new BinaryFormatter(); 20 formatter.Serialize(stream, this); 21 stream.Seek(0, SeekOrigin.Begin); 22 return formatter.Deserialize(stream) as Employee; 23 } 24 } 25 26 //浅拷贝 27 public Employee Shallow() 28 { 29 return this.Clone() as Employee; 30 } 31 }
参考:《编写高质量代码改善C#程序的157个建议》陆敏技
内容总结
以上是互联网集市为您收集整理的C# 浅拷贝和深拷贝的实现全部内容,希望文章能够帮你解决C# 浅拷贝和深拷贝的实现所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。