Monday, September 24, 2007
Recently, I've been using Lutz Roeder's indispensible .NET Reflector to explore how C# 3.0 LINQ query expressions are compiled. To make this easy, the .NET Reflector supports a useful "optimization" setting that specifies which version of the .NET Framework the disassembler should draw features from for code generation. Changing the setting is pretty easy. Just select "Options..." from the "View" menu to display the Options dialog. Then, modify the "Optimization" value on the "Disassembler" page.

Reflector options for optimizing disassembled code to a specific .NET Framework

With the disassembly optimization set to .NET Framework 3.5, here's how a simple query expression looks:

LINQ code disassembled with Reflector and optimized for .NET 3.5

That's pretty cool, but it doesn't really give any insight into the compiler magic happening under the hood. To get a better picture of this, the optimization setting should be changed to ".NET 2.0." Once this is done, the disassembler no longer generates query syntax, and it uses anonymous methods. This makes it plain to see which extension methods are compiled for the different clauses of a query expression. In addition, the method calls are hyperlinked, making it easy to dig deeper.

LINQ code disassembled with Reflector and optimized for .NET 2.0

While this is all very helpful, I do have a few complaints:

  1. I should be able to change the disassembler options on the fly. It'd be great if the Disassembler window sported a toolbar for modifying its options. The current user experience requires me to open the options dialog, make the change, click OK and wait while the .NET Reflector unloads and reloads all of the assemblies that are open. In fact, if I open the options dialog, make no changes and click OK, Reflector will still unload and reload everything. At the risk of inviting comment abuse from Reflector devotees1, I have to say that this strikes me as a pretty lame UI cop out.
  2. The .NET 2.0 optimization isn't accurate because it generates syntax for extension methods. I'm a bit torn by this because this inaccuracy actually makes it easier to understand the code. If this is changed/fixed, there should be an additional option that hides query syntax and shows the underlying method calls with lambda expressions instead of anonymous methods. That way, Reflector could display this LINQ expression:
var query = from m in typeof(String).GetMethods()
            orderby m.Name
            select m.Name;

Like this:

var query = typeof(String).GetMethods().OrderBy(m => m.Name).Select(m => m.Name);

Regardless of these issues, which I hope are addressed (are you reading this, Roeder?!?), the .NET Reflector is a life-changing tool. If it isn't already a part of your developer's toolbox, you should go download it right now.

1I'm one of them.

posted on Monday, September 24, 2007 9:46:09 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on