Why deep cloning? Why shallow cloning? How is this related to references?

R

raylopez99

The "C# Cookbook" (O'Reilly / Jay Hilyard), section 3.26, is on deep
cloning versus shallow cloning. The scanned pages of this book are
found here: http://www.sendspace.com/file/mjyocg (Word format, 3 pp)

My question, coming from a C++ background where deep copying is done,
is why in C# you would do either deep or shallow copying as suggested
by O'Reilly (using the "ICloneable" inhereited interface), at least
for the .NET framework.

I thought references made deep or shallow copying unnecessary? After
all, there's no copy constructor in C#.NET--so why do we need deep or
shallow copying, and why, at least for shallow copying, can't one use
the normal constructor instead? (that is: GenericClass <T> object =
new GenericClass <T> ( ); )

RL


File Name: Cloning.doc
Size: 54KB | Description: C# Cookbook 3.26

http://www.sendspace.com/file/mjyocg

Discussion
Cloning is the ability to make an exact copy (a clone) of an instance
of a type. Clon¬ing may take one of two forms: a shallow copy or a
deep copy. Shallow copying is relatively easy. It involves copying the
object that the Clone method was called on.
The reference type fields in the original object are copied over, as
are the value-type fields. This means that if the original object
contains a field of type StreamWriter, for instance, the cloned object
will point to this same instance of the original object's
StreamWriter; a new object is not created.

There is no need to deal with static fields when performing a cloning
operation. There is only one memory location reserved for each static
field per class, per application domain. Besides, the cloned object
will have access to the same static fields as the original.

Support for shallow copying is implemented by the MemberwiseClone
method of the Object class, which serves as the base class for
all .NET classes. So the following code allows a shallow copy to be
created and returned by the Clone method:
public object Clone( ) {
return (this.MemberwiseClone( ))
}
Making a deep copy is the second way of cloning an object. A deep copy
will make a copy of the original object just as the shallow copy does.
However, a deep copy will also make separate copies of each reference
type field in the original object. Therefore, if the original object
contains a StreamWriter type field, the cloned object will also
contain a StreamWriter type field, but the cloned object's
StreamWriter field will point to a new StreamWriter object, not the
original object's StreamWriter object.
Support for deep copying is not automatically provided by the Clone
method or the .NET Framework. Instead, the following code illustrates
an easy way of implementing a deep copy:
BinaryFormatter BF = new BinaryFormatter( )j MemoryStream memStream =
new MemoryStream( )j
BF.Serialize(memStream, this)j memStream.Flush( )j memStream.Position
= OJ
return (BF.Deserialize(memstream»j
Basically, the original object is serialized out to a memory stream
using binary serialization, then it is deserialized into a new object,
which is returned to the caller. Note that it is important to
reposition the memory stream pointer back to the start of the stream
before calling the Deserialize method; otherwise, an exception
indicating that the serialized object contains no data will be thrown.
Performing a deep copy using object serialization allows the
underlying object to be changed without having to modify the code that
performs the deep copy. If you performed the deep copy by hand, you'd
have to make a new instance of all the instance fields of the original
object and copy them over to the cloned object. This is a tedious
chore in and of itself. If a change is made to the fields of the
object being cloned, the deep copy must also change to reflect this
modification. Using serialization, you rely on the serializer to
dynamically find and serialize all fields contained in the object. If
the object is modified, the serializer will still make a deep copy
without any code modifications.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

raylopez99 said:
My question, coming from a C++ background where deep copying is done,

Not automatically.

Have you ever forgotten to create a copy constructor for a class
with dynamically allocated members ? That is a shallow clone - when
you add the copy constructor and allocate new members, then it becomes
a deep clone.

And while a shallow clone works in .NET due to GC, then it does
not work in C++ with explicit deallocation of memory (unless you
add eksplicit logic to handle it).
is why in C# you would do either deep or shallow copying as suggested
by O'Reilly (using the "ICloneable" inhereited interface), at least
for the .NET framework.

I thought references made deep or shallow copying unnecessary? After
all, there's no copy constructor in C#.NET--so why do we need deep or
shallow copying, and why, at least for shallow copying, can't one use
the normal constructor instead? (that is: GenericClass <T> object =
new GenericClass <T> ( ); )

A shallow clone is much faster to create than a deep clone and if you
do not want to or can not (immutable data types !) change the objects
inside then it is fine.

You need to do a deep clone if you need to be able to update the
objects inside the clone without effecting the objects in the original.

Arne
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

raylopez99 said:
The "C# Cookbook" (O'Reilly / Jay Hilyard), section 3.26, is on deep
cloning versus shallow cloning. The scanned pages of this book are
found here: http://www.sendspace.com/file/mjyocg (Word format, 3 pp)

My question, coming from a C++ background where deep copying is done,
is why in C# you would do either deep or shallow copying as suggested
by O'Reilly (using the "ICloneable" inhereited interface), at least
for the .NET framework.

I thought references made deep or shallow copying unnecessary?

In most cases you don't need to copy objects, but sometimes you might
want to.
After
all, there's no copy constructor in C#.NET--so why do we need deep or
shallow copying, and why, at least for shallow copying, can't one use
the normal constructor instead? (that is: GenericClass <T> object =
new GenericClass <T> ( ); )

If the class has private members, you can't read them from outside the
class, so in that case a method in the class has to do the copying.
Also, it's good to keep the copying code inside the class, for the
reason that if you ever change the members of the class you only have to
change the copying code in one place, not every piece of code where you
copy the object.

Implementing the IClonable interface is a good way of doing the cloning.
It's a standard interface, so anyone that sees it can recognise what
it's doing. You can make a constructor that copies it's values from an
original object that you supply, but it's not as obvious what the
constructor actually does.
 
R

raylopez99

Thanks to Arne and Goran.

I learned from this thread that C#.NET does use deep copying, like C++
(traditional), and arguably even C++.NET.

I also learned why you would want to use the IClonable interface--it
simply is easier than doing it 'by hand' or 'the long way' (which is
the way it is taught in traditional C++). The below language from the
OP (O'Reilly text) says way. Also, like Goran says, other programmers
can read your work and easily figure out what is being done.

The one thing that's a bit confusing--which I'll have to research
using Help--is how binary serialiation works in deep copying, which
seems conceptually intuitive but I'll have to study it a bit more.

RL


"Performing a deep copy using object serialization allows the
underlying object to be changed without having to modify the code
that
performs the deep copy. If you performed the deep copy by hand, you'd
have to make a new instance of all the instance fields of the
original
object and copy them over to the cloned object. This is a tedious
chore in and of itself. If a change is made to the fields of the
object being cloned, the deep copy must also change to reflect this
modification. Using serialization, you rely on the serializer to
dynamically find and serialize all fields contained in the object.
If
the object is modified, the serializer will still make a deep copy
without any code modifications."
 

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