翼度科技»论坛 编程开发 .net 查看内容

list拷贝踩坑记录

8

主题

8

帖子

24

积分

新手上路

Rank: 1

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

一个list集合,元素类型为class,复制一下list,但是list里面元素还是指向原来的对象
  1. internal class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         Console.WriteLine("Hello, World!");
  6.         var lista = new List<People>();
  7.         lista.Add(new People()
  8.         {
  9.             Name = "LaoWang",
  10.             Age= 1
  11.         });
  12.         lista.Add(new People()
  13.         {
  14.             Name = "LaoLi",
  15.             Age = 2
  16.         });
  17.         lista.Add(new People()
  18.         {
  19.             Name = "LaoZhang",
  20.             Age = 3
  21.         });
  22.         var listb = new List<People>(lista);
  23.         listb.Add(new People()
  24.         {
  25.             Name = "LaoLiu",
  26.             Age = 4
  27.         });
  28.         Console.WriteLine("lista:");
  29.         foreach (var item in lista)
  30.         {
  31.             Console.WriteLine(item.Name);
  32.             Console.WriteLine(item.Age);
  33.         }
  34.         Console.WriteLine(" ");
  35.         Console.WriteLine("listb:");
  36.         foreach (var item in listb)
  37.         {
  38.             Console.WriteLine(item.Name);
  39.             Console.WriteLine(item.Age);
  40.         }
  41.     }
  42. }
  43. public record People
  44. {
  45.     public string Name { get; set; }
  46.     public int Age { get; set; }
  47. }
复制代码
输出结果:
  1. Hello, World!
  2. lista:
  3. LaoWang
  4. 1
  5. LaoLi
  6. 2
  7. LaoZhang
  8. 3
  9. listb:
  10. LaoWang
  11. 1
  12. LaoLi
  13. 2
  14. LaoZhang
  15. 3
  16. LaoLiu
  17. 4
复制代码
增加了元素,表面上是没有什么影响的,但是如果我修改呢:
  1. foreach (var item in listb)
  2. {
  3.     item.Name = "DDl";
  4.     item.Age = 8;
  5. }
  6. Console.WriteLine("new lista:");
  7. foreach (var item in lista)
  8. {
  9.     Console.WriteLine(item.Name);
  10.     Console.WriteLine(item.Age);
  11. }
  12. Console.WriteLine(" ");
  13. Console.WriteLine("new listb:");
  14. foreach (var item in listb)
  15. {
  16.     Console.WriteLine(item.Name);
  17.     Console.WriteLine(item.Age);
  18. }
复制代码
结果变成了:
  1. new lista:
  2. DDl 8
  3. DDl 8
  4. DDl 8
  5. new listb:
  6. DDl 8
  7. DDl 8
  8. DDl 8
  9. DDl 8
复制代码
连带着以前的一起改了,这可不是我们想要的结果。所以这种复制算浅克隆。
如何连元素一起复制(深克隆)


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

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

来源:https://www.cnblogs.com/guoxiaotian/p/18529053
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具