LINQ is awesome. It allows us to write powerful, succinct, and expressive code that’s a pleasure to read and maintain. When LINQ was first introduced, way back when in the days of yore (circa 2007), it ushered in a new day in C# development and opened up the new and exciting world of functional constructs to the unsuspecting masses of imperative C# programmers. Nine-ish years later, and you’ll be hard pressed to find a modern C# code-base that doesn’t use LINQ all over the place, and with good reason: LINQ code tells you the story of what we’re doing, instead of telling you the nuts and bolts of how we’re doing it. It’s the essence of clean code.
Debugging LINQ queries, on the other hand, is a completely different story. When you’re using LINQ, you’re essentially sacrificing the debuggability of your code for the readability of your code. If you F10 over a line of code that’s using LINQ - you’ve just performed a whole bunch of complicated logic, but the debugger won’t be helping you figure out what actually happened.
Over the years, developers have come up with a myriad of tricks to make debugging LINQ queries workable. Sometimes they put a breakpoint inside of a lambda expression and hit F5 repeatedly until the breakpoint hit is on the right item (or until their finger gets sore, whichever comes first). Sometimes they split a big query into several smaller queries to make things more workable. In some cases, they end up completely re-writing their LINQ query as imperative code (a bunch of foreach loops) to be able to figure out where things went wrong.
For the past several months, the OzCode team has been fully dedicated to changing the current state of LINQ debugging: our vision is that the more you use LINQ and the functional and beautiful declarative style of programming it enables, your code will actually become easier to debug and maintain.
Today, we’re excited to announce a new way to debug LINQ statements and we’d like to offer you a chance to try it out, by entering the OzCode Early Access Program.
Getting started
► Click here to sign up for the Early Access Program and grab the latest build
As a quick example, we’ve used a LINQ query to generate a FizzBuzz sequence.
Once you reach a line of code that contains a LINQ query, you’ll notice the new numeric indicators:
These indicators show you the number of items returned by each operator. Clicking on one of the numbers will open the LINQ DataTip, which will show you all the items that the LINQ operator produced, or all the items the operator consumed:
When we select an item from the list, the annotations on top of code will update to show us how that specific item “travelled” through the LINQ pipeline, showing us exactly what each lambda expression returned. This powerful visualization will help you instantly understand the flow of your LINQ query. For example, if we select the 3rd item, we can see how it fizzed:
You can quickly run through the different items by using your mouse wheel while hovering over the numeric indicator, like so:
You can also use the OzCode Search functionality to find a specific item in the list.
Get Ready to Fizz and Buzz
But that’s not all!
We’ve also added a new Tool Window that allows you to move through the query pipeline and see exactly what happened in each stage. On the left hand side, you’ll see all the items that came into the operator, and on the right hand side, you’ll see the items that came out of it.
Consider the following query:
var fizzy = Enumerable.Range(1, max)
.Select(i => $"{i} -> {ToFizzBuzz(i)}")
.Where(s => s.Contains("Fizz"))
.ToList();
Opening the new tool window will show us exactly what items passed through the Where
predicate and which items were rejected:
Debugging Exceptions in LINQ Queries
Some of the hardest bugs to tackle are when one of the items inside of a LINQ query causes an exception to be thrown…
Not anymore! OzCode will warn about the exception before it’s thrown, and show you what item caused the exception, enabling you to drill down and find all the information you need to make sure the bug won’t happen again.
In this example, OzCode is showing us that a NullReferenceException is about to occur inside the Where predicate, and we can quickly see that what's causing the issue here is that the Info
Property of one specific Student object is null
:
Wait, there’s more
As part of the Early Access Preview you’ll also get to see some of the new features that we’re going to introduce in OzCode 2.1:
For example, the new & improved Compare, which shows the differences between two (or three, or four) instances, or the same instance over time:
and Export, which enables you to create a textual representation of an object as C# code, Json or XML - this is super-useful when you integrate this new tooling into your Unit Testing workflow.
Found a bug in your debugging session? Spent 10 long minutes just tracking it down, and don’t feel like doing it all over again? Simply Export the faulty object which caused the error, copy-paste the exported output into a new Unit Test, and voilà! Instant regression test.
A few known limitations to LINQ Debugging
- The LINQ feature only works in VS2015.
- The feature works only with the Fluent Syntax of LINQ, and does not work with the Query Comprehension Syntax (The SQL-esque syntax).
- When using a user-defined LINQ operator (meaning one that isn’t a part of Microsoft’s System.Linq), the feature does not show the links between the before and after of that operator (the purple lines in the above figure).
- When the query needs to process a large set of data, the numeric indicators will show a question mark instead of the actual numbers, and only after clicking them to go into LINQ Analysis Mode the real numbers will be revealed.
Keep in mind that this is still an Early-Access-Preview release and as such may contain bugs. If you do find a bug, please let us know - we would like to fix it. Same goes with any thoughts you have on how we could improve the cool new LINQ visualization to better fit your needs!
That’s it for now, so go ahead, download the newly LINQified version of OzCode and let us know what you think!