views:

75

answers:

3

I am trying to optimize a piece of code that clones an object:

#region ICloneable
public object Clone()
{
    MemoryStream buffer = new MemoryStream();
    BinaryFormatter formatter = new BinaryFormatter();

    formatter.Serialize(buffer, this);     // takes 3.2 seconds
    buffer.Position = 0;
    return formatter.Deserialize(buffer);  // takes 2.1 seconds
}
#endregion

Pretty standard stuff. The problem is that the object is pretty beefy and it takes 5.4 seconds (according ANTS Profiler - I am sure there is the profiler overhead, but still).

Is there a better and faster way to clone?

+3  A: 
  1. Don't implement ICloneable.

  2. The fast way to clone an object is to create a new instance of the same type and copy/clone all fields from the original instance to the new instance. Don't try to come up with a "generic" clone method that can clone any object of any class.

Example:

class Person
{
    private string firstname;
    private string lastname;
    private int age;

    public Person(string firstname, string lastname, int age)
    {
        this.firstname = firstname;
        this.lastname = lastname;
        this.age = age;
    }

    public Person Clone()
    {
        return new Person(this.firstname, this.lastname, this.age);
    }
}
dtb
I agree. I'd also like to add an option (3), use an immutable type so that you don't *need* to clone.
Aaronaught
+1  A: 

As I understand it, streams, even inner ones like this, are expensive.
Have you tried to just create a new object it and update the relevant fields to bring the object to the same state? I find it hard to believe your method takes less time.

Rubys
It's rather the reflection used to do the serialisation and deserialisation that is expensive.
Guffa
+1  A: 

That's a pretty expensive way to clone. The object never gets on the wire, so all the time doing serialisation is basically wasted. It will be way faster to do memberwise clone. I realise it's not an automagic solution, but it'll be the fastest.

Something along these lines:

class SuperDuperClassWithLotsAndLotsOfProperties {
  object Clone() {
    return new SuperDuperClassWithLotsAndLotsOfProperties {
      Property1 = Property1,
      Property2 = Property2,
    }

  public string Property1 {get;set;}
  public string Property2 {get;set;}
  }
}
Igor Zevaka