在C#和.NET Core开发中,深拷贝是一个常见的需求。深拷贝与浅拷贝不同,深拷贝会递归地复制对象的所有字段,包括嵌套的对象。本文将介绍C#中实现深拷贝的五大类方法及相应的示例代码。
1. 使用序列化与反序列化
序列化与反序列化是一种常用的实现深拷贝的方法。通过将对象序列化为字节流,然后再反序列化回对象,可以实现对象的深拷贝。
示例代码(二进制序列化):
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
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);
}
}
}
[Serializable]
public class Department
{
public string Name { get; set; }
}
public class Program
{
public static void Main()
{
Student student1 = new Student
{
Name = "Alice",
Age = 20,
Department = new Department { Name = "Computer Science" }
};
Student student2 = (Student)student1.Clone();
student2.Department.Name = "Mathematics";
Console.WriteLine($"Student1 Department: {student1.Department.Name}"); // Output: Student1 Department: Computer Science
Console.WriteLine($"Student2 Department: {student2.Department.Name}"); // Output: Student2 Department: Mathematics
}
}
2. 使用反射
反射是另一种实现深拷贝的方法。通过递归地复制对象的所有字段,可以实现深拷贝。
示例代码(使用反射):
using System;
using System.Reflection;
public class DeepCloner
{
public static T DeepCopy<T>(T obj)
{
if (obj is string || obj.GetType().IsValueType) return obj;
object retval = Activator.CreateInstance(obj.GetType());
FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
field.SetValue(retval, DeepCopy(field.GetValue(obj)));
}
return (T)retval;
}
}
public class Program
{
public static void Main()
{
Student student1 = new Student
{
Name = "Alice",
Age = 20,
Department = new Department { Name = "Computer Science" }
};
Student student2 = DeepCloner.DeepCopy(student1);
student2.Department.Name = "Mathematics";
Console.WriteLine($"Student1 Department: {student1.Department.Name}"); // Output: Student1 Department: Computer Science
Console.WriteLine($"Student2 Department: {student2.Department.Name}"); // Output: Student2 Department: Mathematics
}
}
3. 使用JSON序列化与反序列化
JSON序列化与反序列化也是一种常用的实现深拷贝的方法。通过将对象序列化为JSON字符串,然后再反序列化回对象,可以实现对象的深拷贝。
示例代码(使用Newtonsoft.Json):
using System;
using Newtonsoft.Json;
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
public class Department
{
public string Name { get; set; }
}
public class Program
{
public static void Main()
{
Student student1 = new Student
{
Name = "Alice",
Age = 20,
Department = new Department { Name = "Computer Science" }
};
string json = JsonConvert.SerializeObject(student1);
Student student2 = JsonConvert.DeserializeObject<Student>(json);
student2.Department.Name = "Mathematics";
Console.WriteLine($"Student1 Department: {student1.Department.Name}"); // Output: Student1 Department: Computer Science
Console.WriteLine($"Student2 Department: {student2.Department.Name}"); // Output: Student2 Department: Mathematics
}
}
4. 使用XML序列化与反序列化
与JSON类似,XML序列化与反序列化也是一种实现深拷贝的方法。
示例代码(使用XmlSerializer):
using System;
using System.IO;
using System.Xml.Serialization;
[Serializable]
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
[Serializable]
public class Department
{
public string Name { get; set; }
}
public class Program
{
public static void Main()
{
Student student1 = new Student
{
Name = "Alice",
Age = 20,
Department = new Department { Name = "Computer Science" }
};
string xml;
using (StringWriter stringWriter = new StringWriter())
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Student));
xmlSerializer.Serialize(stringWriter, student1);
xml = stringWriter.ToString();
}
Student student2;
using (StringReader stringReader = new StringReader(xml))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Student));
student2 = (Student)xmlSerializer.Deserialize(stringReader);
}
student2.Department.Name = "Mathematics";
Console.WriteLine($"Student1 Department: {student1.Department.Name}"); // Output: Student1 Department: Computer Science
Console.WriteLine($"Student2 Department: {student2.Department.Name}"); // Output: Student2 Department: Mathematics
}
}
5. 使用第三方库
有许多第三方库提供了深拷贝的功能,如AutoMapper、DeepCloner等。
示例代码(使用AutoMapper):
using System;
using AutoMapper;
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
public class Department
{
public string Name { get; set; }
}
public class Program
{
public static void Main()
{
MapperConfiguration config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Student, Student>();
cfg.CreateMap<Department, Department>();
});
IMapper mapper = config.CreateMapper();
Student student1 = new Student
{
Name = "Alice",
Age = 20,
Department = new Department { Name = "Computer Science" }
};
Student student2 = mapper.Map<Student>(student1);
student2.Department.Name = "Mathematics";
Console.WriteLine($"Student1 Department: {student1.Department.Name}"); // Output: Student1 Department: Computer Science
Console.WriteLine($"Student2 Department: {student2.Department.Name}"); // Output: Student2 Department: Mathematics
}
}
总结
在C#和.NET Core开发中,深拷贝是一个常见的需求。本文介绍了五种实现深拷贝的方法,包括使用序列化与反序列化、反射、JSON序列化与反序列化、XML序列化与反序列化以及第三方库。每种方法都有其适用场景和优缺点,开发者可以根据具体需求选择合适的方法。