C# 浅拷贝和深拷贝的实现
2021-01-06 11:28
标签:ret 引用类型 实现 额外 对象创建 值类型 ide obj string类 拷贝(复制)为对象创建副本,即将对象中的所有字段复制到新的对象(副本中)。拷贝有两种:浅拷贝和深拷贝,微软建议用类型继承ICloneable接口的方式明确该类型是可以被拷贝的,ICloneable接口只提供了一个Clone方法,需要根据需要在Clone方法内实现浅拷贝或深拷贝。 1、浅拷贝:把源对象中的值类型字段的值和引用类型字段的引用复制到副本中。在源对象(副本)中,修改值类型字段的值不会影响到副本(源对象),而修改引用类型字段的值会影响到副本(源对象)。 注意:string类型除外,虽然string类型是引用类型,但是由于该引用类型的特殊性,在浅拷贝过程,副本中会创建新的字符串并把对应的值复制过来,字符串应被看成值类型。 浅拷贝声明代码,使用Object.MeberwiseClone方法进行浅拷贝: 调用浅拷贝代码: 运行结果: 从结果可以看出,Age是值类型,ID是string类型这里被当做值类型处理,所以ID和Age修改了对另一个对象没有影响;Department属性是引用类型,浅拷贝emp1和emp2引用的是同一个Department对象,其中一个修改了DepartmentName的值会影响另一个。 2、深拷贝:把源对象的值类型字段和引用类型字段,重新创建并赋值。在源对象(副本)中,修改值类型字段的值或者引用类型字段的值都不会影响到副本(源对象)。 建议使用序列化的形式来进行深拷贝 深拷贝代码: 跟上面调用浅拷贝代码一样调用深拷贝,运行结果: 拷贝以后,无论是修改值类型还是引用类型,都对另一个对象没有影响。 3、要同时实现深拷贝和浅拷贝,可以在Clone方法外,额外实现两个方法,声明为DeepClone和Shallow: 参考:《编写高质量代码改善C#程序的157个建议》陆敏技 C# 浅拷贝和深拷贝的实现 标签:ret 引用类型 实现 额外 对象创建 值类型 ide obj string类 原文地址:https://www.cnblogs.com/xuyouyou/p/13172411.html
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
[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
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 }