No .NET, há várias formas comuns de implementar uma cópia profunda (deep copy). A cópia profunda significa criar um novo objeto e copiar recursivamente o objeto original e todas as suas referências, em vez de apenas copiar as referências. Neste artigo, vamos explorar os principais métodos para implementar cópia profunda no .NET. Vamos conferir!
1. Usando serialização/deserialização binária
“`csharp
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public static class ObjectCopier
{
public static T DeepCopy<T>(T obj)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException(“O tipo deve ser serializável.”, nameof(obj));
}
if (ReferenceEquals(obj, null))
{
return default;
}
IFormatter formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, obj);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
“`
2. Usando serialização JSON (Newtonsoft.Json ou System.Text.Json)
“`csharp
// Usando Newtonsoft.Json
using Newtonsoft.Json;
public static T DeepCopy<T>(T obj)
{
var json = JsonConvert.SerializeObject(obj);
return JsonConvert.DeserializeObject<T>(json);
}
// Usando System.Text.Json (recomendado a partir do .NET Core 3.0)
using System.Text.Json;
public static T DeepCopy<T>(T obj)
{
var json = JsonSerializer.Serialize(obj);
return JsonSerializer.Deserialize<T>(json);
}
“`
3. Implementando a interface ICloneable (manual)
“`csharp
public class MyClass : ICloneable
{
public int Value { get; set; }
public MyOtherClass Other { get; set; }
public object Clone()
{
var copy = (MyClass)MemberwiseClone(); // cópia superficial
copy.Other = (MyOtherClass)Other.Clone(); // cópia profunda da referência
return copy;
}
}
public class MyOtherClass : ICloneable
{
public string Name { get; set; }
public object Clone()
{
return MemberwiseClone(); // cópia superficial (apenas tipos de valor)
}
}
“`
4. Usando AutoMapper (para objetos complexos)
“`csharp
using AutoMapper;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<MyClass, MyClass>();
cfg.CreateMap<MyOtherClass, MyOtherClass>();
});
var mapper = config.CreateMapper();
var copy = mapper.Map<MyClass>(original);
“`
5. Considerações importantes
* Métodos baseados em serialização exigem que todas as classes envolvidas sejam serializáveis (com o atributo `[Serializable]` ou compatíveis com JSON).
* Referências circulares podem causar estouro de pilha ou exceções de serialização.
* Desempenho: para gráficos de objetos grandes, a serialização pode ser lenta.
* Tipos especiais como delegados ou objetos COM podem não ser copiados corretamente.
6. Métodos recomendados
* Para objetos simples: use serialização JSON (System.Text.Json tem melhor desempenho).
* Para gráficos de objetos complexos: considere implementar `ICloneable` ou usar AutoMapper.
* Para cenários com alta exigência de desempenho: implemente a lógica de cópia profunda manualmente.
A escolha do método mais adequado depende dos requisitos do seu projeto, da complexidade dos objetos e das restrições de desempenho.
📌 Bài viết này được đóng góp bởi người dùng và bản quyền thuộc về người dùng đã xây dựng bài viết. Bản quyền thuộc về tác giả gốc và chỉ dùng cho mục đích học tập và giao tiếp. Nếu có bất kỳ vi phạm nào, vui lòng liên hệ với chúng tôi để xóa nó.
