Thursday, December 11, 2008

I think the best feature introduced in .NET 2.0 was anonymous methods in C#. Hows that for taking a stance!

I've just been reading an article about anonymous methods coming to VB in .NET 4.0 and while I think this is great news for VB developers its worth adding a note of caution due to one of the examples used. Generally anonymous methods and event handlers can cause unforseen issues due to the way anonymous methods are implemented under the covers (I'm assuming the VB implementation is broadly the same as the C# one). If you look at the code below:

class Program
{
    static void Main(string[] args)
    {
        Foo f = new Foo();

        f.ItHappened += delegate
        {
            Console.WriteLine("Foo happens");
        };

        f.ItHappened -= delegate
        {
            Console.WriteLine("Foo happens");
        };

        f.Bar();
    }
}

class Foo
{
    public event Action ItHappened;

    public void Bar()
    {
        if (ItHappened != null)
            ItHappened();
    }
}

The problem is the compiler generates two different real methods for the two anonymous methods. Therefore the unwiring of the handler fails. It comes down to this: if you wire up an event hander with an anonymous method, unless you store the delegate in a variable, there is no way to remove that event handler afterwards. There is a well known issue in .NET in terms of memory leaks with event handlers keeping alive objects that otherwise have independent lifetimes. You fix this issue by remembering to remove the event handler when the object is finished with. However, using anonymous methods (or lambdas for that matter) prevents you from removing the event handler and so this issue becomes unresolvable.

So my advice: even though anonymous methods are very powerful, generally use real methods for event handlers unless the lifetime of the event owner and the subscriber are inherently tied together.

Thursday, December 11, 2008 7:21:46 PM (GMT Standard Time, UTC+00:00)  #    Comments [10]Trackback
Friday, December 12, 2008 9:28:07 AM (GMT Standard Time, UTC+00:00)
This is not entirely true. There will be no memory leaks if you attach an anonymous method to an object and dereference that object because anonymous methods are either static or live in an object created simply for their sake.
This means that the problem is not that there will be memory leaks if you use anonymous methods to attach to events (they will die when the object raising the events is dereferenced), but rather that they will be attached to the event for the entire lifetime of the object. In 99.9% of the cases I've seen to date, this is hardly a problem.
Friday, December 12, 2008 5:22:23 PM (GMT Standard Time, UTC+00:00)
Defeatist!

It's entirely possible to unattach a handler implemented as an anonymous method. It's a little verbose but it's easily done:

Timer t = new Timer();
ElapsedEventHandler h = null;
h = delegate
{
t.Elapsed -= h;
t.Stop();
};
t.Elapsed += h;
t.Interval = 1000;
t.Start();

You simply have to store the method in a variable, and then you can unattach it later. And in this case, because I'm unattaching the handler inside the handler itself, I also had to initialize the variable to null to avoid a compiler error - C# appears not to understand that the field must have been initialized by the time the anonymous method runs.

So it's not quite accurate to say that use of anonymous methods prevents you from removing the handler.

Saturday, December 13, 2008 6:50:23 AM (GMT Standard Time, UTC+00:00)
Hi Omer

Thats not strictly true. If an anonymous method references member variables but not local variables the compiler generates an instance method on the class. Also if the anonymous method captures local state then, as you say, you get a new class - however this local state could be quite large. So if the hte event ownver and subscriber have independent lifetimes then the evet could quite easily keep significant object alive when they should otherwise have been garbage.
Richard
Saturday, December 13, 2008 6:55:39 AM (GMT Standard Time, UTC+00:00)
Hi Ian

yes you are absolutely right. If you store all your event handlers in variables you can indeed unsubscribe them. Unfortunately this is not a particularly useful pattern in general. Alsom although its a neat trick to unsubscribe in the event handler - the decision to rely on the event being raised so that you can unsubscribe is fairly dangerous. I have amended the post to satisfy your pendatry however :-P
Richard
Saturday, December 13, 2008 9:04:22 AM (GMT Standard Time, UTC+00:00)
Richard,

My point is that these are edge cases (I have yet to encounter one) and that your call to not use anonymous methods in event handlers is a bit too general.

(also, it would have been nice to know my email address would have been published before inputting it; that's just plain not nice of your blog)
Saturday, December 13, 2008 9:22:20 AM (GMT Standard Time, UTC+00:00)
Hi Omer,

my call was to not use them "unless the lifetime of the event owner and the subscriber are inherently tied together". In the most common cases teh lifetimes are tied together (controls on a window for example). Situations where they are not tied together anonymous methods can potentially cause bugs which are hard to track down.

Sorry that you didn't realise that your email address would be shown (although obfuscated to some degree from spam engines). I will see if Das Blog has some setting to hide them
Richard
Monday, June 28, 2010 5:31:49 AM (GMT Daylight Time, UTC+01:00)
You write articles, I read the original views of other authors related articles, but feel that you are the best. You know, and comparison of industry comprehensive knowledge very attract me. Hope you to write more and better articles sharing
Monday, June 28, 2010 5:32:43 AM (GMT Daylight Time, UTC+01:00)
flywowgold why is really good?is my website.
Tuesday, August 24, 2010 8:55:05 PM (GMT Daylight Time, UTC+01:00)
Do you recognize that it's high time to receive the <a href="http://bestfinance-blog.com/topics/mortgage-loans">mortgage loans</a>, which can help you.
Monday, September 06, 2010 1:39:13 AM (GMT Daylight Time, UTC+01:00)
Vielen Dank! Super Artikel! Wenn Sie Elektronik möchten,Können Sie im unser efox-shop suchen.wir bieten Videospiele Zubehör ,PSP Zubehör ,Nintendo Wii Zubehör usw.
welcome you to : http://www.efox-shop.com/
Die besten Dual SIM Handys, <a href="http://www.efox-shop.com/pc-videospiele-c-236.html/"> Videospiele Zubehör </a.>.
Vielen Dank! Super Artikel! Wenn Sie Elektronik möchten,Können Sie im unser efox-shop suchen.wir bieten NDSLZubehör , NDSL Zubehör , NDSi Zubehör , Nintendo DS Lite Zubehör AND Konsolen usw.
welcome you to : http://www.efox-shop.com/ Die besten Dual SIM Handys, <a href="www.efox-shop.com/pc-videospiele-ndslndsi-zubehör-c-236_391.html">NDSLZubehör</a>,
Vielen Dank! Super Artikel! Wenn Sie Elektronik möchten,Können Sie im unser efox-shop suchen.wir bieten Wii Zubehör kaufen AND PS2Zubehör ,Playstation 2-Spiele, diverses Zubehöre usw.
welcome you to : http://www.efox-shop.com/ Die besten Dual SIM Handys, <a href="www.efox-shop.com/pc-videospiele-sony-ps2-zubehör-c-236_398.html">PS2Zubehör</a.>,
Vielen Dank! Super Artikel! Wenn Sie Elektronik möchten,Können Sie im unser efox-shop suchen.wir bieten Autoteile, Auto Zubehör,Auto Schmuck ,Kfz Zubehör AND China GPS , Navigation Gerät AND Auto GPS Gerät kaufen AND Konsolen usw.
welcome you to : http://www.efox-shop.com/pc-videospiele-china-spiel-konsole-c-236_395.html Die besten Dual SIM Handys, <a href=" www.efox-shop.com/pc-videospiele-china-spiel-konsole-c-236_395.html "> Konsolen </a.>,
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):