【发布时间】:2011-03-29 17:36:41
【问题描述】:
我想创建深拷贝方法,我找到了 3 种方法来执行它
1-deep copy 将每个属性一一传递
2-使用反射
3-使用序列化
请问哪一个在性能方面是最好的
【问题讨论】:
标签: c#
我想创建深拷贝方法,我找到了 3 种方法来执行它
1-deep copy 将每个属性一一传递
2-使用反射
3-使用序列化
请问哪一个在性能方面是最好的
【问题讨论】:
标签: c#
第一个选项,手动深度复制您的值,将是迄今为止性能最高的。
反射会引入相当多的开销,因为它(相对)访问数据很慢。
序列化增加了巨大的成本,因为它将数据序列化为一个临时结构,然后将过程反向设置。这又是,非常慢。
选项 2 或 3 的唯一优点是它可能更容易实现,并且可以跨多种类型重用。第一个选项必须按类型手写,但速度要快得多(也比选项 3 更有效地使用内存)。
【讨论】:
我用三种方法的比较加上一个表达式树方法制作了图表。
对于大量对象,反射比序列化快 5 倍,手动代码和表达式树比序列化快 20 倍。因此,性能最好的是手动代码和表达式树。
使用的克隆代码链接(2.-4.用作扩展方法):
【讨论】:
您列出可能的解决方案的顺序是正确的性能顺序。
当您编写代码以手动克隆每个属性值时,您将获得最佳性能。
反射将产生与手动克隆类似的结果,但速度稍慢。
序列化是最糟糕的情况。但实施起来最快。
Here is a good article that describes other possible solutions.
所以这里列出了所有可能的克隆方法:
我个人会选择“Clone with IL”,因为它比反射略快,而且您不必手动克隆所有内容。
【讨论】:
最好的性能是在您的代码中创建克隆。所以“1”的方式。
【讨论】:
有ICloneable 接口。如果克隆 ICloneable 的东西,使用它的方法是最好的解决方案
【讨论】:
听起来您已经完成了寻找方法的艰苦工作,所以现在您必须在您的特定情况下对它们进行测试并找出答案。
在大多数情况下,这实际上取决于您要序列化的什么数据
【讨论】:
反射可用于生成比手动复制更有效的 DynamicMethod(可以通过 skipVisibilityCheck 访问直接打破范围的字段来复制自动属性)。 DynamicMethod 为您提供一个委托,您可以保留在静态只读字段中以克隆您的对象。这是快速简便的方法,但不是最干净的。 序列化很慢而且不适应。
【讨论】:
作为CGbR 的作者,我想邀请您尝试一下您的用例。
您只需要nuget package 和实现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 倍。
【讨论】: