DeepClone(使用二进制序列化)与手动设置属性的性能

leo*_*ora 8 c# performance clone

我有一组对象,我试图克隆这个集合,并试图了解不同方法的性能含义.

集合中的对象具有大约20个属性,所有字符串,整数,浮点数(此对象内部没有任何嵌套对象).这两种方法是:

  1. 创建DeepClone()方法:

    public static class ExtensionMethods
    {
        public static T DeepClone<T>(this T a)
        {
           using (var stream = new MemoryStream())
           {
               var formatter = new BinaryFormatter();
               formatter.Serialize(stream, a);
               stream.Position = 0;
              return (T)formatter.Deserialize(stream);
           }
       }
    
    Run Code Online (Sandbox Code Playgroud)

    }

  2. 手动编写"复制"代码,我循环访问集合并"新"一个新对象,然后手动设置所有20个属性.这样的事情

     public MyObject Copy(MyObject myObj)
    {
     var obj = new MyObject();
     obj.Prop1 = myObj.Prop1;
     obj.Prop2 = myObj.Prop2;
     return obj;
    
    Run Code Online (Sandbox Code Playgroud)

    }

我得到了非常不一致的结果,所以我希望得到人们的反馈:

  1. 一个人应该比另一个快得多吗?我会想到选择二,但我的测试似乎不支持这个,所以我想弄清楚我做错了什么.

  2. 有没有办法更快地做到这一点?

Gle*_*eno 5

好吧,首先BinaryFormatter路线肯定要慢一些,因为它使用反射来获取/设置属性.最常用的方法是将IClonable接口与复制构造函数结合使用.

class A : ICloneable
{
    private readonly int _member;

    public A(int member)
    {
        _member = member;
    }

    public A(A a)
    {
        _member = a._member;
    }

    public object Clone()
    {
        return new A(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

当然严格来说,你只需要复制构造函数,这应该是最快的方法.如果您的对象很简单,您应该尝试使用内置的MemberwiseClone函数.

class A : ICloneable
{
    private readonly int _member;

    public A(int member)
    {
        _member = member;
    }

    public object Clone()
    {
        return MemberwiseClone();
    }
}
Run Code Online (Sandbox Code Playgroud)

同时,我编写了一些测试代码,以查看MemberwiseClone()是否比使用复制构造函数更快或更慢.你可以在这里找到它.我发现MemberwiseClone实际上比执行CopyConstructor慢得多,至少在小类上是这样.请注意,使用BinaryFormatter非常慢.