C#深浅拷贝的深入解析
拷贝是编程中的常见操作,其中深浅拷贝是我们需要重点关注的。本文将介绍深浅拷贝的概念和实现方法,让初学者掌握如何正确实现深浅拷贝。
概念
深浅拷贝是针对引用类型而言的。
- 浅拷贝:将引用类型的变量复制一份,但是仍然是复制的引用,即两个引用变量还是指向同一个对象。
- 深拷贝:将引用类型的变量复制一份,并且将其中的引用类型也复制一份,即两个引用变量指向的是两个不同的对象。
浅拷贝的实现
浅拷贝可以通过 C# 中的 MemberwiseClone()
方法来实现。
public class Student : ICloneable
{
public int Id { get; set; }
public string Name { get; set; }
public Teacher Teacher { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
public class Teacher
{
public int Id { get; set; }
public string Name { get; set; }
}
如上代码示例中,Student 类包含了一个 Teacher 类型的引用变量。如果我们现在需要复制一个 Student 对象,只需要使用 MemberwiseClone() 方法即可。
Student student1 = new Student { Id = 1, Name = "小明", Teacher = new Teacher { Id = 1, Name = "张老师" }};
Student student2 = (Student)student1.Clone();
student2.Id = 2;
student2.Teacher.Name = "王老师";
Console.WriteLine($"student1.Name = {student1.Name}"); // 小明
Console.WriteLine($"student2.Name = {student2.Name}"); // 小明
Console.WriteLine($"student1.Teacher.Name = {student1.Teacher.Name}"); // 王老师
Console.WriteLine($"student2.Teacher.Name = {student2.Teacher.Name}"); // 王老师
上述示例代码中,我们使用了 MemberwiseClone() 方法来浅拷贝 Student 对象,并修改了 student2 的属性值和 Teacher 对象的属性值。从输出结果可以看出,student2 和 student1 的 Name 属性相同,这是因为 Name 是一个值类型,而 Teacher 的 Name 属性值不同,这是因为 Teacher 本身是一个引用类型,此时修改了其值,student1 和 student2 指向的是同一个 Teacher 对象,因此输出结果都为 "王老师"。
深拷贝的实现
深拷贝需要遍历所有的引用类型,并将其也进行拷贝。一般采用序列化与反序列化,或者对每个引用类型的类手动实现 Clone() 方法。
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class Student : ICloneable
{
public int Id { get; set; }
public string Name { get; set; }
public Teacher Teacher { get; set; }
public object Clone()
{
var student = (Student)this.MemberwiseClone();
student.Teacher = (Teacher)this.Teacher.Clone();
return student;
}
}
public class Teacher : ICloneable
{
public int Id { get; set; }
public string Name { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
如上代码示例中,我们在 Student 类中的 Clone() 方法中对 Teacher 引用类型进行了拷贝,并且手动实现了 Teacher 类的 Clone() 方法来完成深拷贝。
还可以使用序列化实现深拷贝,示例代码如下:
public static T DeepCopy<T>(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T)formatter.Deserialize(ms);
}
}
示例说明:
Student student1 = new Student { Id = 1, Name = "小明", Teacher = new Teacher { Id = 1, Name = "张老师" }};
Student student3 = DeepCopy<Student>(student1);
student3.Id = 3;
student3.Teacher.Name = "王老师";
Console.WriteLine($"student1.Id = {student1.Id}"); // 1
Console.WriteLine($"student3.Id = {student3.Id}"); // 3
Console.WriteLine($"student1.Teacher.Name = {student1.Teacher.Name}"); // 张老师
Console.WriteLine($"student3.Teacher.Name = {student3.Teacher.Name}"); // 王老师
上述示例代码中,在 DeepCopy() 方法中使用了 BinaryFormatter 序列化和反序列化实现了深拷贝。输出结果与前一个示例相同,代码的实现更加简洁。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#深浅拷贝的深入解析 - Python技术站