BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News The Dark Side of Closures

The Dark Side of Closures

Bookmarks

Closures are not a new concept and in LINQ have proven to be incredibly useful. But they do have a dark side when used to break encapsulation. When two seemingly independent functions are tied together, unexpected results can occur.

Closures allow functions to share their local variables with anonymous functions defined within them. These anonymous functions, often referred to as lambdas, are essential to creating the strongly typed queries exposed by LINQ.

In his experiments with LINQ, Dustin Campbell discovered that queries could be altered while they were running. That's right, by changing a local value that was closed over, the function used in the where clause is modified. If this is done while the query is running, the query may acknowledge that change and respond accordingly.

Dustin uses this trick to create a query that only returns distinct items. To start with, the where clause is set to the expression "m.Name != filter". Each time an item is returned, the value of filter is updated to be the last name returned. Under the right circumstances, this can effectively create a list of distinct items.

However, it is an incredibly fragile technique. In Dustin's case, the list had to sorted prior to applying the where clause. If done the other way around, all the filtering will occur before any items are returned and there will be no chance to alter it. This can be done in LINQ because where and order by clauses can appear in any order.

Something Dustin did not mention is that this will not work for all providers. Those that send the query to an outside engine like LINQ to SQL will also not get a chance to alter the where clause. It gets even worse if you try to use Parallel LINQ. Because it is running on multiple threads, any change to the where clause will result in a race condition.

Of course the right answer is to simply call Distinct() and be done with it. While these tricks are academically interesting, they are certain to lead to subtle bugs and are very susceptible to changes in the framework.

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

  • The dark side of Java

    by Eirik Maus,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Non-private static variables can be used like global variables, breaking encapsulation, OO-principles and the like. BOOHAA! Java is probably useless until 'static' is removed.

  • Re: The dark side of Java

    by Jonathan Allen,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    While technically true, closures are a lot more subtle than static variables. You can always tell a static variable by looking at its definition; closures require you to read the entire method for instances of the variable. Thus more care needs to be taken with them.

  • Misnamed

    by Rafael de F. Ferreira,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    This entry really should have been named "The dark side of mutable state". If your procedure values only close over immutable state, this "problem" simply disappears.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT