【声明】优快云只做转发不做时时更新,最新博客请关注博客园 .NET 数据拷贝方案选择 - 唐宋元明清2188 - 博客园
应用中我们经常使用到数据的复制,在.NET中有多种方式可以实现复制数据或对象。选择哪种方式、是浅拷贝还是深拷贝,具体需求场景可以取决于对象的复杂性、数据量等,本文我们介绍主要的拷贝方式以及相对高性能的方案。
1. MemberwiseClone拷贝
浅拷贝 Object.MemberwiseClone 方法 (System) | Microsoft Learn,指针对对象执行非静态字段的浅复制操作
- 字段是基础类型如string、int,会全部复制过来,是全新的值
- 字段是引用类型,则会则复制对象的引用,而不复制对象,二者对象是一个内存地址
深拷贝,则不管是字段还是引用类型,均完全实现全新的复现。
一般深拷贝可以手动实现,对象类内部添加Clone方法(也可以实现内置的统一接口ICloneable),将所有字段重新赋值一遍、返回一个新对象。那也可以基于MemberwiseClone方案之上,对引用类型重新赋值一个新对象,实现深拷贝
深拷贝,内部克隆的对象字段可以修改,不会影响原来对象的值。
参考如下代码:
1 public class MemberwiseCloneModel 2 { 3 public int Age { get; set; } 4 public string Name { get; set; } 5 public TestMode Mode { get; set; } 6 public MemberwiseCloneModel ShallowClone() 7 { 8 return (MemberwiseCloneModel)this.MemberwiseClone(); 9 } 10 public MemberwiseCloneModel DeepCopy() 11 { 12 var clone = (MemberwiseCloneModel)this.MemberwiseClone(); 13 clone.Mode = new TestMode() { Data = this.Mode?.Data ?? string.Empty }; 14 return clone; 15 } 16 }
2.Record的with数据拷贝
这是针对Record数据类的一类拷贝方式,只在C#9以上支持,详见Record - C# reference | Microsoft Learn
record因为是标记数据类,可以只有属性,所以RecordModel可以简写为RecordModel1结构:
1 public record class RecordModel 2 { 3 public string Name { get; set; } 4 public int Age { get; set; } 5 public TestMode Mode { get; set; } 6 } 7 public record RecordModel1(string Name, int Age, TestMode Mode);
with相当于MemberwiseClone浅拷贝,对值类型字段可以全新复制,但引用类型操作后还是同一对象 with 表达式 - 创建新对象,这些对象是现有对象的修改副本 - C# reference | Microsoft Learn
写个demo:
1 public static void TestRecordWith() 2 { 3 var origin