需要复制一个类,类里有引用类型字段,字段里可能还存在嵌套的引用类型。
想要深度复制,复制后各字段值相同,但互不相干,改变一个类引用类型的值后,不会影响被复制者的对应值。
自己解决需求时遇到的问题如下:
1:最开始用MemberwiseClone写了一大堆觉得真好用,等测试的时候才发现这是浅复制,导致bug一大堆。
2.1:然后去网上复制代码多套,但都有各自的问题。第一套:
T tOut = Activator.CreateInstance();
Type tInType = this.GetType();
PropertyInfo[] array = tOut.GetType().GetProperties();
for (int i = 0; i
这一段代码的速度是令人满意的,10万次在我电脑上大约1.6秒,可以接受。但复制结果不对,遇到list他不复制,而是直接给我new一个新的空list出来,这导致list里的数据会全部为空。
2.2:第二套:
T model = Activator.CreateInstance(); //实例化一个T类型对象
PropertyInfo[] propertyInfos = model.GetType().GetProperties(); //获取T对象的所有公共属性
foreach (PropertyInfo propertyInfo in propertyInfos)
{
//判断值是否为空,如果空赋值为null见else
if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable)))
{
//如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换
NullableConverter nullableConverter = new(propertyInfo.PropertyType);
//将convertsionType转换为nullable对的基础基元类型
propertyInfo.SetValue(model, Convert.ChangeType(propertyInfo.GetValue(this), nullableConverter.UnderlyingType), null);
}
else
{
propertyInfo.SetValue(model, Convert.ChangeType(propertyInfo.GetValue(this), propertyInfo.PropertyType), null);
}
}
return model;
问题和第一套一样,效率一致但还只是半浅半深的复制。
2.3:第三套 json序列化,这一套解决了复制不够深的问题,但效率略低,跑10万次花了接近19秒(如果本帖求不到更好的解决方法,我也只能用这个方法凑合用了)
string 序列化内容 = JsonConvert.SerializeObject(this);
T? 新 = JsonConvert.DeserializeObject(序列化内容);
return 新;
2.4:第四套 我看不懂但跑了一下,效率低的离谱,10万次花了60秒!(可是某乎上说,AutoMapper方法运行很快,一百万次才300多毫秒??是我复制的代码写的不好还是什么问题?怎么效率差这么多?)
var config = new MapperConfiguration(cfg =>
{
// 针对每一层嵌套的类型进行映射配置
cfg.CreateMap();
cfg.CreateMap();
});
// 创建映射器
IMapper mapper = config.CreateMapper();
// 使用映射器进行深度复制
T 新 = mapper.Map(this);
return 新;
2.5:还有有大佬用 BinaryFormatter 这种方法写,说是挺好用的,但我也测试不了,因为这个已经被弃用了,代码无法通过检查。我也找不到他的平替品。
最后又看到有人说手写复制最快,一行行代码挨个赋值,遇到引用类型再去引用类型里写手写复制……
有点难绷,要是真手写我可能要多写上千行,而且后面万一新增点什么东西,还容易错写漏写。
问题总结:
深度多层复制一个类的方法,要求效率比json序列化快5倍以上即可。
我电脑用json方法跑10万次耗时19秒,不求像浅复制那样10万次跑进1秒之内的方法,好歹能有一个10万次跑4秒以内的方法吧?否则太慢真让人不舒服。
★希望大佬给出的是完整可运行代码,而不是思路。因为大佬们看我的描述也知道我是个圈外人,不是程序员,写的东西都是很浅显的,没有经过系统的学习,您们给我说个思路我真没法玩……
跪谢!