Click here to Skip to main content
Click here to Skip to main content

Events and Clones

, 19 Apr 2004
Rate this:
Please Sign up or sign in to vote.
Care needs to be taken when using Events and Clones.

Introduction

When using C# Events and MemberwiseClone, you can end up with some undesirable side effects. You can unwittingly end up leaking memory and/or get weird behavior. This article describes the problem with events and clones and gives a guideline on how to avoid these problems.

The Problem with Events and MemberwiseClone

If you use MemberwiseClone, it will clone any event the object has. This means the newly cloned object will fire off events to whatever objects were registered with the object you cloned from. This tends to be undesirable for a number of reasons:

  • The object that registered an interest in receiving events from the original object is now getting events from the newly cloned object also.
  • Because the object that registered for an event doesn't know about the newly cloned object, it doesn't know to deregister its interest from the cloned object.
  • Because events hold references to objects, it can cause objects to hang around in memory after you think you have killed all references to that object

Another thing to keep in mind about Events is that if you register your interest twice, you will have to deregister your interest twice before you will stop receiving events. To stop this, you can do a deregister before registering. If you hadn't registered before, the deregistration will do nothing. Then add your registration, if you had registered before, it will delete your registration then re-add it. E.g.

Owner.TheEvent -=new EventOwner.Handler(HandleIt);
Owner.TheEvent +=new EventOwner.Handler(HandleIt);

A Solution to the problem

Simplest solution is not to use MemberwiseClone when you have an object with events. Instead, you can use CopyFrom as the following example shows:

public void CopyFrom(ObjectWithEvent anObject)
{
    // copy members, but not events....
}

object ICloneable.Clone()
{
    return Clone();
}

public ObjectWithEvent Clone()
{
    ObjectWithEvent clone = new ObjectWithEvent();
    clone.CopyFrom(this);
    return clone;
}

The disadvantage of this is that you have to explicitly copy each field in your class inside your CopyFrom. Each time you add fields to your class, you also have to remember to update the CopyFrom. However, a further improvement is to use reflection to do the copy and recognize any events and not copy them.

Another thing to keep in mind with objects that register an interest in an event and also use CopyFrom is that they need to deregister their interest in events before copying from the other object. Once you have copied from the other object, you then re-register your interest. If you fail to do this, you will start receiving events from two objects.

public void CopyFrom(MyType anotherType)
{
    EventOwner.TheEvent -=new EventOwner.Handler(HandleIt);
    EventOwner = anotherType.EventOwner;
    EventOwner.TheEvent +=new EventOwner.Handler(HandleIt);
}

It can also be worth writing a Dispose method that deregisters your interest in Events. If you don't do this, the object that fires events will maintain a reference to your object and keep it alive. If the object that fires the event lasts for the application's lifetime, this can cause what seems to be a memory leak. It is also useful for the object firing events to know that all objects interested in its events are gone. E.g.

public void Dispose()
{
    Owner.TheEvent -=new EventOwner.Handler(HandleIt);
}

History

  • 25th February 2004 - Created.
  • 15th April 2004 - Turned into CodeProject article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Keith Nicholas
Web Developer
New Zealand New Zealand
No Biography provided

Comments and Discussions

 
QuestionCLone windows Pinmembermesiasrojo12-Aug-11 1:43 
GeneralDo not use MemberwiseClone Pinsussdvemil20-Apr-04 22:02 
GeneralAnother approach Pinmemberleppie20-Apr-04 8:20 
GeneralCode Pinmemberalper20-Apr-04 2:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 20 Apr 2004
Article Copyright 2004 by Keith Nicholas
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid