我想创建深拷贝方法,并找到了三种执行方法
1-逐个传递每个属性进行深拷贝
2-使用反射
3-使用序列化
请问它们中哪一种在性能方面最好?
首选项是手动深度复制您的值,这将具有远高于其他选项的性能。
反射会引入相当多的开销,因为访问数据相对较慢。
序列化会增加很大的成本,因为它将数据序列化到临时结构中,然后再反转该过程进行设置。这也是非常慢的。
选项2或3唯一的优点是它可能更容易实现,并可重用于多种类型。而第一种选项必须针对每种类型手动编写,但比选项3更快(并且在内存使用效率方面更高)。
将你列出的可能解决方案按正确的性能顺序排序。
当您编写代码手动克隆每个属性值时,您将获得最佳性能。
反射将产生与手动克隆类似的结果,但速度稍慢。
序列化是最糟糕的情况。但实现最快。
所以这里是所有可能的克隆方法列表:
我个人会选择"使用IL克隆",因为它比反射略快,并且您不必手动克隆所有内容。
ICloneable
接口的部分类定义。生成器将会自动生成一个文件和一个 Clone(bool deep)
方法。public partial class Root : ICloneable
{
public Root(int number)
{
_number = number;
}
private int _number;
public Partial[] Partials { get; set; }
public IList<ulong> Numbers { get; set; }
public object Clone()
{
return Clone(true);
}
private Root()
{
}
}
public partial class Root
{
public Root Clone(bool deep)
{
var copy = new Root();
// All value types can be simply copied
copy._number = _number;
if (deep)
{
// In a deep clone the references are cloned
var tempPartials = new Partial[Partials.Length];
for (var i = 0; i < Partials.Length; i++)
{
var value = Partials[i];
value = value.Clone(true);
tempPartials[i] = value;
}
copy.Partials = tempPartials;
var tempNumbers = new List<ulong>(Numbers.Count);
for (var i = 0; i < Numbers.Count; i++)
{
var value = Numbers[i];
tempNumbers[i] = value;
}
copy.Numbers = tempNumbers;
}
else
{
// In a shallow clone only references are copied
copy.Partials = Partials;
copy.Numbers = Numbers;
}
return copy;
}
}
性能:在我们工作中需要克隆的基准测试中,我们将其与DataContractSerializer
和MemoryStream
进行了比较。生成的代码快了600倍。
看起来你已经做好了找到解决方案的艰苦工作,现在你需要在特定情况下测试它们所有,并找出最好的方案。
大部分情况下,这真的取决于你所序列化的数据的种类。
反射可以用于生成DynamicMethod,这比手动复制更有效(自动属性可以通过直接访问字段来复制,跳过作用域并绕过可见性检查)。 DynamicMethod为您提供了一个委托,您可以将其保存在静态只读字段中以克隆对象。这是快速简便的方法,但不一定是最干净的方法。 序列化速度慢且不适合。