Recently, I've been using Lutz Roeder's
indispensible .NET Reflector
to explore how C# 3.0
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"
With the disassembly optimization set to .NET Framework 3.5, here's how a
simple query expression looks:
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
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.
While this is all very helpful,
I do have a few complaints:
- 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.
- 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()
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.