Take care to unhook Anonymous Delegates

Posted by David Vallens on Geeks with Blogs See other posts from Geeks with Blogs or by David Vallens
Published on Wed, 23 Nov 2011 09:50:10 GMT Indexed on 2011/11/23 17:52 UTC
Read the original article Hit count: 275

Filed under:

Anonymous delegates are great, they elimiante the need for lots of small classes that just pass values around, however care needs to be taken when using them, as they are not automatically unhooked when the function you created them in returns. In fact after it returns there is no way to unhook them.

Consider the following code.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
			SimpleEventSource t = new SimpleEventSource();
			t.FireEvent();
			FunctionWithAnonymousDelegate(t);
			t.FireEvent();
		
		}

		private static void FunctionWithAnonymousDelegate(SimpleEventSource t)
		{
			t.MyEvent += delegate(object sender, EventArgs args)
			{
				Debug.WriteLine("Anonymous delegate called");
			};
			t.FireEvent();
		}
	}

	public class SimpleEventSource
	{
		public event EventHandler MyEvent;

		public void FireEvent()
		{
			if (MyEvent == null)
			{
				Debug.WriteLine("Attempting to fire event - but no ones listening");
			}
			else
			{
				Debug.WriteLine("Firing event");
				MyEvent(this, EventArgs.Empty);
			}
		}
	}
}

If you expected the anonymous delegates do die with the function that created it then you would expect the output

Attempting to fire event - but no ones listening
Firing event
Anonymous delegate called
Attempting to fire event - but no ones listening

However what you actually get is

Attempting to fire event - but no ones listening
Firing event
Anonymous delegate called
Firing event
Anonymous delegate called

In my example the issue is just slowing things down, but if your delegate modifies objects, then you could end up with dificult to diagnose bugs.

A solution to this problem is to unhook the delegate within the function

var myDelegate = delegate(){Console.WriteLine("I did it!");};
MyEvent += myDelegate;
// .... later
MyEvent -= myDelegate;

© Geeks with Blogs or respective owner