When stepping through code you sometimes encounter unexpected results. Unexpected results are frequently interesting because they can reveal details about the code that were previously unknown, and they are a smell indicating a logic error or bad data. Unfortunately the time from the moment you see the unexpected result to the moment you understand why is frequently measured in minutes, not seconds. Drilling down into a complex expression or reviewing historical data leading to a potential issue involves way too many mouse clicks and keyboard shortcuts, and may even require a restart in an attempt to catch the problem where it happens. Unraveling complexity is often tedious and may require intense focus.
The Debug Visualizer is here to dramatically reduce the time between unexpected behavior and complete understanding.
Here’s how it works.
Historic Visual Record
As you step into a method the Debug Visualizer immediately gets to work, revealing values for any arguments passed into the method.
Figure 1: The Debug Visualizer acting like a Locals window, but without the messy window.
Those local values you see just below the arguments persist as you step through this method, serving as a sort of historical document on the original values on entry or assignment, which may be useful if those later change inside the method.
See Changes Right Where They Occur
When values change as you step through the code, you’ll see those changes immediately. For example, in the screenshot below we can see the value of surfaceAreaOfCylinder is 0.0.
Figure 2. An assignment statement before execution.
Stepping over this line of code updates the local variable’s value, shown in red on the left:
Figure 3. Now we can easily see which line of code changed a variable.
Showing Function Results
One debugging task that takes far too many steps and too much time is determining the value of a function that returns a calculation. There seems to be no easy way to get to this important information quickly.
Fortunately the Debug Visualizer makes this pain a thing of the past. Now when you step up to a return statement, you can see the value returned before you leave the function:
Figure 4: Easily see calculated values that functions return.
Revealing the Future
In addition to documenting the past, the Debug Visualizer can also reveal the future. Step through the code and you’ll see the values for expressions on the active line before they are executed. For example, in the code below, the Math.Sqrt() call has not been executed yet, however the future result, 42.0, can be seen right below the expression:
Figure 5: The future revealed, and the answer is… 42?
If there is an unexpected value on the current line, many times it’s useful to know this before the line executes. It’s much easier to step into a method call or property getter before the line executes than after:
|Stepping into a Method Call or Property Getter:
Before the Line Executes
After the Line Executes
|Press F11 or Ctrl+Shift+F11||
- Move the caret back to the problem line which might be far away if an exception occurred
- Press Ctrl+Shift+F10 to set the active line
- Wait for the line to become active
- Press F11 or Ctrl+Shift+F11
The future previews are here to save all those extra steps and waiting.
Values of expressions involving potential side-effects that may impact program behavior are not predicted; you’ll see a Refresh button instead. Click the button or press Ctrl+R to see the values.
So, what happens when you encounter an unexpected value while debugging? For this section, we’ll use a simple code example, however you might want to imagine this working on an expression with greater complexity.
Figure 6: An unexpected value.
With the caret anywhere on the active statement, press Alt+Down to bring up the Expression Explorer.
Figure 7: Drilling into the expression.
The Expression Explorer lets you drill into individual expression parts and see their corresponding values. In the screenshot above we can see the result of the call to Math.Sqrt() is 4.58 (we were expecting 5), and that the value of the expression passed into the Sqrt call is 21.0(expecting 25).
Once the Expression Explorer is up, you can move around and drill into expression parts with the arrow keys. For example, pressing theDown arrow (using the example code above) reveals the children of the active expression:
Figure 8. Drilling further... aSide * aSide == 9.0
The Node Map to the right shows a hierarchical representation of the expression. You can drag this window to reposition it if needed.
Figure 9. The Node Map reveals the active node (emphasized with high-contrast), parent nodes in purple, other nodes in blue, and collapsed child nodes in gray.
Notice the high-contrast active node on the left contains two collapsed children (in gray). Sometimes you just want to peek at the child values without actually changing the active expression. We can toggle child expression visibility by pressing the spacebar. Doing so in our example code produces the following:
Figure 10. Spacebar toggles child expression visibility.
In the screenshot above, we can see the 9.0 comes from 3.0 * 3.0.
We can collapse child expressions with the spacebar as well. Pressing spacebar again produces this:
Figure 11. Collapsing the child expressions with the spacebar.
The “9.0” value shown above for the “aSide * aSide” expression is expected, and the child expression values look good. Our problem must be elsewhere. Let’s move right.
Figure 12. Continuing to explore…
Expressions and their corresponding values are always left-aligned.
Figure 13. Values are displayed below a thick horizontal bar that lines up with the corresponding expression above.
Let’s move down into the child expressions with the Down arrow.
And to the right with the Right arrow:
And now we can see our problem. This reference to “aSide” should have been a reference to “bSide”. Now we just need to fix the code. You can close the Expression Explorer by pressing Escape, or by clicking anywhere else in the editor. When the Expression Explorer closes, the code looks like this:
Figure 16. The Expression Explorer has closed, and we can still see the last values explored.
With Edit and Continue enabled we can fix the code. As soon as we make any change to the code the Debug Visualizer clears the historical data in the active method.
Figure 17. After editing.
Of course, after editing, you can show the Expression Explorer again by pressing Alt+Down.
Figure 18. Results are now as expected.
Here’s the Expression Explorer in action:
And here’s the Expression Explorer scaling up to a more complex expression:
Figure 19. The Expression Explorer scales to handle complex code.
Why is this Expression False (or True)?
Sometimes when stepping through code with Boolean expressions an unexpected result appears. When this happens, the Expression Explorer can help you quickly understand why. For example, in this method we want to rent/hire a car. However the Debug Visualizer tells us this won’t happen by showing the “false” value below the expression:
Figure 20. The Debug Visualizer optionally adorns Boolean expressions with “ ” (true) or “ ” (false) icons.
So to find out why this expression is false, we press Alt+Down to bring up the Expression Explorer:
Figure 21. Conclusive Boolean expressions are emphasized with bold green text in the code and with squares in the Node Map.
Now we immediately see the problem. It is here, highlighted in green:
Figure 22. Conclusive Boolean expressions determine the value of their parent expressions
A parent Boolean expression might contain more than one conclusive Boolean child expression. However in this code, there is only one.
Let’s drill down to get more detail. Press the Right arrow to move right and select the conclusive Boolean expression:
Figure 23. The conclusive Boolean expression, shown as a square in the Node Map, is selected.
And now press the Down arrow (or spacebar) to see the children of this expression:
Figure 24. And now we see why we can’t rent/hire the car.
Highlighting conclusive expressions is useful for understanding why Boolean expressions are true or false.
Evaluating Expressions with Side Effects
Sometimes an expression might contain a method call or property getter access with potential side-effects. If CodeRush is unable to verify a call is free of side-effects, the Debug Visualizer will display a Refresh button. As long as the line of code is active you can click this button (or Press Ctrl+R) to call into the method and get the result.
Figure 25. Calls with potential side-effects (for example, the call to “Directory.Exists”) are highlighted.
Note that even though an expression preview may be marked with a Refresh button, you can still drill down into its children to see their values without refreshing. For example, in the screenshot above, the Exists call prevents evaluation of the parent expression, however you can still see an evaluation of the “drive + path” expression.