UPDATE:
After i've been proven wrong in the comments below I have to say this:
Go take a read of this article to see how circular references are really handled.
While Delegate.GetInvocationList() really is a great and usefull thing and it could be used in clearing up events,
there's no need for it since you can do that as easily by simply unsubscribin from the event when
you want to dispose your class.
You can read this post on, but know that this example is WRONG, except for the last part about
Observer pattern and WeakEvent pattern.
Maybe you should read this post since sometimes you can learn how stuff works by reading how it doesn't work :))
---------------------------------------------------------------------------------------------------------------------------------------
Subscribed events are one of the most common reasons of memory leaks in .Net. This means that if you have an object that has an event
and there are other object that are subscribed to that event, the original object won't be properly disposed until all events are unsubscribed since
an event is a strong reference.
A simple example of this is a form called MyForm that has a public event called OnDoMyFormThing and 5 classes are subscribed to this event.
When the OnDoMyFormThing is executed on the form it will notify all 5 classes. You might call this event a few more times depending on what your form does.
After this the form is closed. However the form isn't disposed until all 5 classes that are subscribed to the event get disposed. A hard way of doing this
would be to somehow implement the event removal on all 5 classes.
An easy way would be to do this in the Dispose method of the form itself. But how, if you don't know the name of every event handler.
But remeber that an event is just a delegate. And delegates have a GetInvocationList() method.
GetInvocationList() gets an array of delegates. Each delegate represents a method subscribed to an event. The order of the delgates is the same as the
invocation order of the subscribed methods on the event.
So your code in MyForm would be:
public partial class MyForm : Form
{
public event EventHandler OnDoMyFormThing;
public MyForm()
{
InitializeComponent();
}
private void button1_OnClick
{
MessageBox.Show("Test of OnDoMyFormThing event");
OnDoMyFormThing(this, new EventArgs());
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
foreach (EventHandler eventDelegate in OnDoMyFormThing.GetInvocationList())
OnDoMyFormThing -= eventDelegate;
components.Dispose();
}
base.Dispose(disposing);
}
}
And with this your form can be disposed normally.
Event subscriptions in 5 classes look like this:
class1.MyForm.OnDoMyFormThing += Class1EventHandler
class2.MyForm.OnDoMyFormThing += Class2EventHandler
class3.MyForm.OnDoMyFormThing += Class3EventHandler
class4.MyForm.OnDoMyFormThing += Class4EventHandler
class5.MyForm.OnDoMyFormThing += Class5EventHandler
The strong bidirectional reference between an event and its subscriptions is a common problem in all Observer pattern scenarions, so you must
know about it and care about it. If not, you're sure to get memory leaks.
In .Net ramework 3.0 there is a pattern called WeakEvent that you can use to create a weak reference to events and not really care about disposal.