克隆性能更佳

时间:2011-03-29 17:36:41

标签: c#

我想创建深层复制方法,我找到了3种方法来执行它

1个深度复制,每个属性1乘1

2 - 使用反射

3 - 使用序列化

请他们哪一个是表现最好的

8 个答案:

答案 0 :(得分:13)

第一个选项是手动深度复制你的值,到目前为止效果最好。

反射会引入相当多的开销,因为它(相对)访问数据的速度很慢。

序列化增加了巨大的成本,因为它将数据序列化为临时结构,然后反转要设置的进程。这又是非常缓慢的。

选项2或3的唯一优势是它可能更容易实现,并且可以跨多种类型重用。第一个选项必须是每种类型的手写,但速度要快得多(内存使用效率也高于选项3)。

答案 1 :(得分:8)

我用三种方法和表达式树方法比较制作了图表。

enter image description here

对于大量对象,反射快5倍手动代码和表达式树比序列化快20倍。因此,性能最佳的是手动代码和表达式树。

使用过的克隆代码的链接(2.-4。用作扩展方法):

  1. 手动:手动编写,无链接。
  2. Cloning by Serialization
  3. Cloning by Reflection
  4. Cloning by Expression Trees

答案 2 :(得分:7)

订购时,您列出的可能的解决方案是正确的性能订单。

当您编写代码以手动克隆每个属性值时,您将获得最佳性能。

反射与手动克隆有相似的结果,但速度稍慢。

序列化是最糟糕的情况。但最快实施。

Here is a good article that describes other possible solutions.

所以这里列出了所有可能的克隆方法:

  1. 手动克隆
  2. Clone with MemberwiseClone
  3. Clone with Reflection
  4. Clone with Serialization
  5. Clone with IL
  6. Clone with Extension Methods
  7. 我个人会选择“Clone with IL”,因为它比反射快一点,您不必手动克隆所有内容。

答案 3 :(得分:2)

最佳性能是在代码中创建克隆。所以“1”的方式。

答案 4 :(得分:1)

ICloneable界面。如果克隆某些ICloneable,使用其方法将是最佳解决方案

答案 5 :(得分:0)

听起来你已经完成了找到方法的艰苦工作,所以现在你必须在特定的情况下测试它们并找出答案。

在大多数情况下,它实际上取决于您要序列化的数据

答案 6 :(得分:0)

可以使用反射来生成DynamicMethod,它比手动复制更有效(可以通过访问直接通过skipVisibilityCheck打破范围的字段来复制自动属性)。 DynamicMethod为您提供了一个委托,您可以将其保存在静态只读字段中以克隆您的对象。这是快速简便的方法,但不是最干净的。 序列化很慢而且没有适应。

答案 7 :(得分:0)

作为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;
    }
}

效果:在我们工作所需的克隆基准测试中,将其与DataContractSerializerMemoryStream进行比较。生成的代码快600倍。