Much can be written in response to this deceptively simple question! In fact, I have written at length in my article LINQ Secrets Revealed: Chaining and Debugging on Simple-Talk.com. Here is a summary of its key points:
- You can step into some LINQ queries with the debugger, but it depends on the composition of expressions and statements in the query (because you can only step onto statements).
- A LINQ method chain works because of a fundamental rule: each non-terminal method takes
IEnumerable<T>
as input and returns IEnumerable<T>
as output.
- You can inject a "no-op" statement to give you a "stepping stone", if you will, as long as it conforms to that fundamental rule. That is, realizing that you could always put
.Select(z => z)
in a method chain without consequence, use a variation of that, to wit: z => { return z; }
.
- You can similarly inject a diagnostic method to provide output rather than just provide a potential breakpoint. LINQPad, the outstanding scratchpad for not just LINQ but C# in general, provides this in the guise of its powerful
Dump()
method. Dump is an object visualizer that provides amazing visualizations of complex data structures.
- Based on work by Bart De Smet in his informative article LINQ to Objects – Debugging you can bring a simplified flavor of
Dump
back into Visual Studio--I provide code attached to my article mentioned at the top.
- Thanks to Robert Ivanc's work on LINQPad Visualizer you can even bring the LINQPad visualizer into Visual Studio (though you need to fire it off manually for individual expressions; you cannot hook it up to a
Dump()
method).
As a brief example, consider this simple method chain:
string[] Words = new string[]
{" KOOKABURRA", "Frogmouth", "kingfisher ", "loon", "merganser"};
Words
.Select(word => word.Trim())
.Select(word => word.ToLower())
.Where(word => word.StartsWith("k"))
.OrderBy(word => word);
Once you include the Dump extension method in your Visual Studio project, you can minimally instrument it like this...
Words
.Select(word => word.Trim())
.Dump()
.Select(word => word.ToLower())
.Dump()
.Where(word => word.StartsWith("k"))
.Dump()
.OrderBy(word => word)
.Dump();
... or more elaborately like this...
Words
.Dump(w => "ORIGINAL: " + w, ConsoleColor.Yellow)
.Select(word => word.Trim())
.Dump(w => "TRIMMED: " + w, ConsoleColor.Yellow)
.Select(word => word.ToLower())
.Dump(w => "LOWERCASE: " + w, ConsoleColor.Green)
.Where(word => word.StartsWith("k"))
.Dump(w => "FILTERED to 'K': " + w, ConsoleColor.Red)
.OrderBy(word => word)
.Dump(w => "SORTED: " + w, ConsoleColor.Blue);
... to get output rendered as either the left side or right side of the figure, respectively:

As a teaser, I will say that while this is indeed useful, you really must see the enhanced visualization that LINQPad can do with the same output (here is the link again for your convenience).