469,572 Members | 1,232 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,572 developers. It's quick & easy.

IClonable

If I want to implement an IClonable interface, how can I copy the events
from my source object to the target "cloned" object?
Nov 15 '05 #1
5 3466
If I want to implement an IClonable interface, how can I copy the events
from my source object to the target "cloned" object?

class CloneableWithEvents : ICloneable
{
public event MyDelegate MyEvent;

public object Clone()
{
CloneableWithEvents clone = new CloneableWithEvents();
clone.MyEvent += MyEvent;
return clone;
}
}

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #2

"Mattias Sjogren" <ma********************@mvps.org> wrote in message
news:uZ****************@TK2MSFTNGP10.phx.gbl...
If I want to implement an IClonable interface, how can I copy the events
from my source object to the target "cloned" object?

class CloneableWithEvents : ICloneable
{
public event MyDelegate MyEvent;

public object Clone()
{
CloneableWithEvents clone = new CloneableWithEvents();
clone.MyEvent += MyEvent;
return clone;
}
}


wouldn't

CloneableWithEvents clone = (CloneableWithEvents)this.MemberwiseClone();

be simpler? It catches private fields, including events(assuming they are
normal fields, not in a hash table or anything, and it will work when
overridden, the above method breaks when you inherit from it.

Mattias

--
Mattias Sjogren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Nov 15 '05 #3
Daniel,
wouldn't

CloneableWithEvents clone = (CloneableWithEvents)this.MemberwiseClone();

be simpler?
In this case, sure. But simpler isn't always better. :-) I didn't mean
to provide the definite way do handle this, just to show that it's
pretty straight forward and doesn't require any special magic.

It catches private fields, including events(assuming they are
normal fields, not in a hash table or anything, and it will work when
overridden,
MyEvent isn't virtual so you can't override it. ;-)

the above method breaks when you inherit from it.


If you expect your class to be inherited from (in code you don't
control) I would strongly suggest you avoid MemberwiseClone. You don't
know if the derived data can be safely be copied like that, or if it
for example references some unmanaged resource.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 15 '05 #4
thank's

"Mattias Sjögren" <ma********************@mvps.org> schrieb im Newsbeitrag
news:uZ****************@TK2MSFTNGP10.phx.gbl...
If I want to implement an IClonable interface, how can I copy the events
from my source object to the target "cloned" object?

class CloneableWithEvents : ICloneable
{
public event MyDelegate MyEvent;

public object Clone()
{
CloneableWithEvents clone = new CloneableWithEvents();
clone.MyEvent += MyEvent;
return clone;
}
}

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Nov 15 '05 #5
> If you expect your class to be inherited from (in code you don't
control) I would strongly suggest you avoid MemberwiseClone. You don't
know if the derived data can be safely be copied like that, or if it
for example references some unmanaged resource.


You're missing the point of MemberwiseClone then.

The correct way to clone a base-class object is as follows:

public virtual object Clone()
{
//perform shallow copies of all members, even derived ones
MyClass clone = (MyClass)MemberwiseClone();

//perform deep copies where required
clone.deepCopyValue = (ContainedClass)deepCopyValue.Clone();

//I usually disconnect any events here, actually
//since I don't usually want event handlers cloned

//finally
return clone;
}
This way any sub-classes of MyClass will automatically get a correct clone
of the base class. If the derived classes need a deep copy of anything
else, they can override Clone as follows:

public override object Clone() {
//allow base class to do its work, and deep copy anything it needs to
MySubClass clone = (MySubClass)base.Clone();

//if any of the derived members need to be deep-copied, do that here:
clone.collection = new MyCollection(collection);

return clone;
}

It's up to each class to deep-copy any members that it needs. If the
sub-class fails to do so, it's the fault of the sub-class. At least with
the base-class using MemberwiseClone, sub-classes don't need to override
Clone unless they need to provide further deep-copying. Many times,
shallow-copies are perfectly acceptable.

If you don't use this method, you either need to provide a means for
sub-classes to safely clone all of the members of the base class (by making
them protected, perhaps), or through the use of
copy-constructor-like-semmantics (which then require all sub-classes to
follow a pattern which isn't very intuative to most C# programmers).

Using any other method (especially methods where Clone isn't marked virtual)
makes it the job of every derived class to ensure that the base class is
cloned properly.

Using the method I've described makes it the job of each class to deep-copy
only the members that it needs to. Sub-classes need not worry about how to
clone the parent class. This helps versioning as well---in case the parent
class introduces new members that require deep copies that the child class
is not aware of.

It seems to me that NOT using MemberwiseClone is more fragile than using it.
Or am I missing some obvious better way to implement cloning? I know
copy-constructors can work, but it's not nearly as elegant as a virtual
Clone implemented with MemberwiseClone and further deep copying.

--Matthew W. Jackson
Nov 15 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by AMerrell | last post: by
2 posts views Thread by Dan | last post: by
7 posts views Thread by Tiësto | last post: by
14 posts views Thread by Arne | last post: by
2 posts views Thread by Nathan | last post: by
6 posts views Thread by Larry Minton | last post: by
15 posts views Thread by Gustaf | last post: by
4 posts views Thread by guiromero | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.