Deep Clones

R

richard d

I can basically see two ways of doing this, in both cases implementing
Clone() from the ICloneable interface:

Given:

class A : ICloneable { ... }
class B : A { ... }

1)

In (A)

public virtual object Clone() { return new A(this); }
protected A (A clonee) { /* copy from clonee, making further clones of
members where appropriate */ }

In (B)

public override object Clone() { return new B(this); }
protected B (B clonee) : base(clonee) { /* copy from clonee, making
furhter clones of members where appropriate */ }

This is the C++ way

2)

In (A)

public object Clone() { A clone = MemberwiseClone() as A;
clone.MakeDeep() ; return clone; }
protected virutal void MakeDeep() { /* replace shallow member copies
with deep copies */ }

In (B)

protected override void MakeDeep() { base.MakeDeep(); /* replace
shallow member copies with deep copies */ }

- What looks like the new c# way.

Unless MemberwiseClone is doing something behind the scenes, and this
might just be personal preference, I like method (1) better.

Is it just personal preference?

All the best

Richard
 
L

Lasse Vågsæther Karlsen

richard said:
I can basically see two ways of doing this, in both cases implementing
Clone() from the ICloneable interface:

Given:

class A : ICloneable { ... }
class B : A { ... }

1)

In (A)

public virtual object Clone() { return new A(this); }
protected A (A clonee) { /* copy from clonee, making further clones of
members where appropriate */ }

In (B)

public override object Clone() { return new B(this); }
protected B (B clonee) : base(clonee) { /* copy from clonee, making
furhter clones of members where appropriate */ }

This is the C++ way

2)

In (A)

public object Clone() { A clone = MemberwiseClone() as A;
clone.MakeDeep() ; return clone; }
protected virutal void MakeDeep() { /* replace shallow member copies
with deep copies */ }

In (B)

protected override void MakeDeep() { base.MakeDeep(); /* replace
shallow member copies with deep copies */ }

- What looks like the new c# way.

Unless MemberwiseClone is doing something behind the scenes, and this
might just be personal preference, I like method (1) better.

Is it just personal preference?

All the best

Richard

Cloning is unfortunately a process that "sounds simple" when you look at
it from a birdseye view perspective, but gets really hard to do right
when you get to the details.

For instance, what if you have this scenario:

- object
- containing an array of other objects
- and those objects contains references to yet another set of objects
- and some of those array-objects contains reference to the same object

what then?

either you:

- clone the referenced object twice, meaning they no longer reference
the same object
- track used objects and their clones

Also, how deep do you clone?

For instance, if a property deep deep down in one object references some
kind of database session (ORM-kind of object), do you clone this as
well? Can it be cloned?

To my knowledge, it is not easy to build a generic deep cloning facility
without explicit knowledge about what you're going to clone, which
usually means that you write all the code anyway.

The typical choice is to implement ISerializable, and just serialize the
object to a memory stream and deserialize back. The serialization
process handles the problem with multiple references to the same object,
but will still have problems with objects not meant for serialization
(that you want to clone nonetheless).
 
R

richard d

Cloning is unfortunately a process that "sounds simple" when you look at
it from a birdseye view perspective, but gets really hard to do right
when you get to the details.

For instance, what if you have this scenario:

- object
- containing an array of other objects
- and those objects contains references to yet another set of objects
- and some of those array-objects contains reference to the same object

what then?

either you:

- clone the referenced object twice, meaning they no longer reference
the same object
- track used objects and their clones

Also, how deep do you clone?

For instance, if a property deep deep down in one object references some
kind of database session (ORM-kind of object), do you clone this as
well? Can it be cloned?

To my knowledge, it is not easy to build a generic deep cloning facility
without explicit knowledge about what you're going to clone, which
usually means that you write all the code anyway.

The typical choice is to implement ISerializable, and just serialize the
object to a memory stream and deserialize back. The serialization
process handles the problem with multiple references to the same object,
but will still have problems with objects not meant for serialization
(that you want to clone nonetheless).

I don't believe that you can create a general purpose cloning system.
Every individual class must decide what shallow copies and what deep
copies.

In C++, you have to do this thing with extreme precision, as you have
to worry about memory leaks. I would always prefix a member reference
with "o_" to indicate that the referred object was "owned" by this
object (and, obviously, an object can only have 1 owner). I thought
with c# I could abandon this practice, and indeed I have, but I think
I should bring it back. A deep clone method would then deep clone the
"o_" references and shallow copy the rest.

Oddly enough I've gone for option (2) above for implementation,
because I decided it was quicker to write, since you can miss out
MakeDeep implementations in classes which have no "o_"s.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top