## 引言 深拷貝是指創建一個新對象,該對象的值與原始對象完全相同,但在記憶體中具有不同的地址。這意味著如果您對原始對象進行更改,則不會影響到複製的對象 常見的C#常見的深拷貝方式有以下4類: 1. 各種形式的序列化及反序列化。 2. 通過反射機制獲取該對象的所有欄位和屬性信息。遍歷所有欄位和屬性,遞 ...
引言
深拷貝是指創建一個新對象,該對象的值與原始對象完全相同,但在記憶體中具有不同的地址。這意味著如果您對原始對象進行更改,則不會影響到複製的對象
常見的C#常見的深拷貝方式有以下4類:
- 各種形式的序列化及反序列化。
- 通過反射機制獲取該對象的所有欄位和屬性信息。遍歷所有欄位和屬性,遞歸將源對象中的值複製到目標對象中。
- 新建對象,手動複製所有成員變數。
- 實現
ICloneable
介面,重寫Colne
方法。方法內部可以調用上面任意實現方法。
序列化、反序列化
使用二進位序列化和反序列化
可以使用 BinaryFormatter
類將對象序列化成二進位形式並保存到文件或記憶體流中,然後再使用 BinaryFormatter
反序列化對象,這樣就可以得到該對象的一個完全獨立的副本。
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
return default(T);
}
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Seek(0, SeekOrigin.Begin);
T copy = (T)formatter.Deserialize(stream);
stream.Close();
return copy;
}
使用 XML 序列化和反序列化
可以使用 XmlSerializer
類將對象序列化成 XML
形式並保存到文件或記憶體流中,然後再使用 XmlSerializer
反序列化對象,這樣也可以得到該對象的一個完全獨立的副本。
using System.IO;
using System.Xml.Serialization;
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
return default(T);
}
XmlSerializer serializer = new XmlSerializer(typeof(T));
MemoryStream stream = new MemoryStream();
serializer.Serialize(stream, obj);
stream.Seek(0, SeekOrigin.Begin);
T copy = (T)serializer.Deserialize(stream);
stream.Close();
return copy;
}
使用 DataContractSerializer 序列化和反序列化
可以使用 DataContractSerializer 類將對象序列化成 XML 或二進位形式並保存到文件或記憶體流中,然後再使用 DataContractSerializer 反序列化對象。
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization.Formatters.Binary;
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
return default(T);
}
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
MemoryStream stream = new MemoryStream();
serializer.WriteObject(stream, obj);
stream.Seek(0, SeekOrigin.Begin);
T copy = (T)serializer.ReadObject(stream);
stream.Close();
return copy;
}
使用 Json.NET 或 System.Text.Json 序列化和反序列化
可以使用 JsonConvert 類將對象序列化成 JSON 字元串,然後再使用 JsonConvert 反序列化對象。
using Newtonsoft.Json;
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
return default(T);
}
string json = JsonConvert.SerializeObject(obj);
T copy = JsonConvert.DeserializeObject<T>(json);
return copy;
}
using System.Text.Json;
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
return default(T);
}
string jsonString = JsonSerializer.Serialize<T>(obj);
// 將 JSON 字元串反序列化為對象
var deserializedPerson = JsonSerializer.Deserialize<T>(jsonString);
return deserializedPerson;
}
反射
使用反射實現深拷貝
通過反射生成對象,通過反射機制獲取該對象的所有欄位和屬性信息。遍歷所有欄位和屬性,以遞歸方式將源對象中的值複製到目標對象中。
using System;
using System.Reflection;
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
return default(T);
}
Type type = obj.GetType();
object copy = Activator.CreateInstance(type);
// 獲取所有欄位和屬性信息,並將源對象中的值複製到目標對象中
foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
object value = fieldInfo.GetValue(obj);
fieldInfo.SetValue(copy, DeepCopy(value));
}
foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
if (!propertyInfo.CanWrite || !propertyInfo.CanRead)
{
continue;
}
object value = propertyInfo.GetValue(obj);
propertyInfo.SetValue(copy, DeepCopy(value));
}
return (T)copy;
}
手動賦值
手動複製所有成員變數
可以手動編寫代碼複製對象中的所有成員變數,這需要對對象結構有很好的瞭解,並且比較繁瑣,容易漏掉某些成員。
public class Person
{
public string Name;
public int Age;
public Person DeepCopy()
{
Person copy = new Person();
copy.Name = this.Name;
copy.Age = this.Age;
return copy;
}
}
ICloneable 介面
實現 ICloneable 介面
可以在對象中實現 ICloneable
介面,並重寫 Clone
方法來實現深拷貝。重寫的 Clone
方法內可以調用上述任何一種方案。
public class Person : ICloneable
{
public string Name;
public int Age;
public object Clone()
{
Person copy = new Person();
copy.Name = this.Name;
copy.Age = this.Age;
return copy;
}
}
第三方庫
還有一種方式是使用第三方庫實現深拷貝,例如 AutoMapper、ValueInjecter 等。這些庫可以自動複製對象中的所有成員變數,從而實現深拷貝。
其中比較常用的包括:
-
AutoMapper:這是一個非常流行的對象映射庫,可以用於將一個對象的屬性值複製到另一個對象中,從而實現對象深拷貝。
-
Newtonsoft.Json:這是一個廣泛使用的 JSON 序列化/反序列化庫,它也提供了一些方法來實現對象深拷貝。
-
Cloneable:這是一個專門為 .NET 平臺設計的對象克隆庫,它提供了多種深拷貝和淺拷貝的方式。
-
FastDeepCloner:這是一個高性能的對象複製庫,它支持對任意類型進行深拷貝,並且提供了多種可配置選項。
可以需要根據自己的具體需求選擇適合自己的庫。如果只是需要簡單的深拷貝操作,那麼 AutoMapper 和 Newtonsoft.Json 都是不錯的選擇;如果需要更加高效、靈活的操作,那麼可以考慮使用 FastDeepCloner 或 Cloneable 等庫。
作者: Niuery Daily
出處: https://www.cnblogs.com/pandefu/>
關於作者:.Net Framework,.Net Core ,WindowsForm,WPF ,控制項庫,多線程
本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出 原文鏈接,否則保留追究法律責任的權利。 如有問題, 可郵件咨詢。