list拷贝踩坑记录

  • list拷贝踩坑记录已关闭评论
  • 23 次浏览
  • A+
所属分类:.NET技术
摘要

最近做项目中,有一个场景需要复制list给其他对象的属性赋值,然后再去根据对象的其他属性操作list的元素数据,其实就是一个list的拷贝问题


最近做项目中,有一个场景需要复制list给其他对象的属性赋值,然后再去根据对象的其他属性操作list的元素数据,其实就是一个list的拷贝问题

代码还原

一个list集合,元素类型为class,复制一下list,但是list里面元素还是指向原来的对象

internal class Program {     static void Main(string[] args)     {         Console.WriteLine("Hello, World!");         var lista = new List<People>();         lista.Add(new People()         {             Name = "LaoWang",             Age= 1         });         lista.Add(new People()          {             Name = "LaoLi",             Age = 2         });         lista.Add(new People()         {             Name = "LaoZhang",             Age = 3         });          var listb = new List<People>(lista);         listb.Add(new People()         {             Name = "LaoLiu",             Age = 4         });          Console.WriteLine("lista:");         foreach (var item in lista)         {             Console.WriteLine(item.Name);             Console.WriteLine(item.Age);         }          Console.WriteLine(" ");         Console.WriteLine("listb:");         foreach (var item in listb)         {             Console.WriteLine(item.Name);             Console.WriteLine(item.Age);         }      } }  public record People {     public string Name { get; set; }      public int Age { get; set; } } 

输出结果:

Hello, World! lista: LaoWang 1 LaoLi 2 LaoZhang 3  listb: LaoWang 1 LaoLi 2 LaoZhang 3 LaoLiu 4 

增加了元素,表面上是没有什么影响的,但是如果我修改呢:

foreach (var item in listb) {     item.Name = "DDl";     item.Age = 8; }  Console.WriteLine("new lista:"); foreach (var item in lista) {     Console.WriteLine(item.Name);     Console.WriteLine(item.Age); }  Console.WriteLine(" "); Console.WriteLine("new listb:"); foreach (var item in listb) {     Console.WriteLine(item.Name);     Console.WriteLine(item.Age); } 

结果变成了:

new lista: DDl 8 DDl 8 DDl 8 new listb: DDl 8 DDl 8 DDl 8 DDl 8 

连带着以前的一起改了,这可不是我们想要的结果。所以这种复制算浅克隆。

如何连元素一起复制(深克隆)

  1. 手动复制,foreach 循环 new对象手动插入新的list
  2. 第三方工具 automapper等
  3. 序列化和反序列化,通过将对象序列化为一个字节流,然后再反序列化回来,可以实现深克隆
  4. 表达式树或者反射,代码如下
public static T DeepClone<T>(T obj) {     using (var ms = new MemoryStream())     {         var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();         formatter.Serialize(ms, obj);         ms.Seek(0, SeekOrigin.Begin);         return (T)formatter.Deserialize(ms);     } }  public static List<T> DeepCloneList<T>(List<T> list) {     return list.Select(item => DeepClone(item)).ToList(); } 

总结

以前由于经常做类似的,理解还是很清楚,好久不做到了现在一下就踩坑了,所以为了以后不继续踩坑,决定记录下来。