Visual Studio 2019 Debugging Productivity Tips

Introduction

 
We assume that the reader knows the basics of debugging in Visual Studio but we will dive into some major concepts in debugging.
 
Many developers handle their debugging sessions with this powerful-enough knowledge kit. However, Visual Studio Debugging tools have much more to offer. Here is a list of Visual Studio Debugging productivity tips. Note that those tips and shortcuts have been validated with Visual studio 201916.6 with no extension installed.
 

Run to Cursor

 
With the shortcut Ctrl+F10, you can tell the debugger to run until the line pointed by the cursor.
 
Visual Studio 2019 Debugging Productivity Tips 
 

Run Execution through here with a simple mouse click 

 
When hovering the source code while debugging a Run execution through here a green glyph appears. This glyph can be clicked.
 
Visual Studio 2019 Debugging Productivity Tips 
 

Set next statement to here 

 
The Run execution through here green glyph can be transformed into set next statement to here by holding the key Ctrl. It is different than Run execution through here because the statement in between is not executed. Hence in the small animation below, we can see in the watch window that the reference obj remains null: MyClass constructor in between hasn't been executed.
 
Visual Studio 2019 Debugging Productivity Tips 
 

Data breakpoint hit: when value changes 

 
If you set a breakpoint to a non-static property setter it will be hit when changing the property value for all objects. The same behavior can be obtained for a single object thanks to the local (or watch) window right-click: Break when the value changes the menu.
 
This facility is illustrated with the animation above. The hit occurs only when obj2.Prop is changed, not when obj.Prop is changed.
 
Note that a data breakpoint is bound to a live object during a debugging session. Hence it gets lost once the debugged process stops, it cannot be reused during the future debugging sessions.
 
Note that the menu breaks when value changes are also available when right-clicking a field in the local's window but unfortunately the debugger doesn't break on-field change, I am not sure if it's a bug or a feature not yet implemented?
 
Visual Studio 2019 Debugging Productivity Tips 
 

Conditional Breakpoint

 
A condition can be attached to a breakpoint to break only in a certain scenario. In the animation below we define the breakpoint with the condition I > 6 within the loop. Then we click Continue and can see that once the breakpoint is stopped, the Ivalue is actually 7.
 
 
Visual Studio 2019 Debugging Productivity Tips
 

Trace Breakpoint

 
Halting the program execution is the most common action upon a breakpoint hit. However, you can choose instead to print some traces in the Output window without (or with) halting. This possibility is illustrated by the animation below where we trace the value of I from 0 to 9 in the Output window. Notice that a trace breakpoint has the diamond shape in the code editor gutter.
 
Note that both a condition and a trace action can be specified on a breakpoint.
 
Visual Studio 2019 Debugging Productivity Tips 
 

Tracking an object whose reference goes Out-Of-Scope

 
In the Watch, window objects are tracked by the name of their references in the currently executed scope. However when such tracked reference goes out-of-scope, it becomes meaningless in the context of the Watch window and it gets disabled, even though the referenced object is still alive.
 
There are many situations where we’d like to continue tracking the state of an out-of-scope object. To do so, right-click such reference in the Watch window, click the menu Make Object ID and add $1 in the items to watch (or $2 or $3… depending on how many object IDs you’ve already created).
 
The animation below shows how to track the state of an out-of-scope object’s property getter that returns the actual date-time as a string. It shows well that when the reference obj goes out-of-scope in the context of Fct(), obj item to watch gets disabled and $1.Prop still gets updated.
 
Visual Studio 2019 Debugging Productivity Tips 
 

View the value returned by a function

 
The value returned by a function is sometimes ignored by the source code. Or sometime this value is just not obviously accessible at debug-time.
 
Such returned value can be shown in the Debug > Windows > Autos windows. The pseudovariables$ReturnValue can also be used in the Immediate and Watch Windows view the last function call returned value.
 
Note that the menu Debug > Windows > Autos is available only when the Visual Studio debugger is attached to a process and the program is halted by the debugger.
 
Visual Studio 2019 Debugging Productivity Tips
 

Reattach to Process

 
Since Visual Studio 2017 the Reattach to processShift+Alt+P facility is proposed and it’s very handy. Once you’ve been attaching the debugger to a process Visual Studio remembers it and proposes to re-attach the debugger to the same process. Same is in italic because there is a heuristic here about the process identity:
  • If the process you’ve been attached to is still alive Reattach to process re-attach to it.
  • Else Visual Studio attempts to find a single process with the same previous process name and re-attach the debugger to it.
  • If several processes are found with this name, the Attach to Process dialog is opened with only those processes with the same name shown
  • If no process with this name can be found the Attach to Process dialog is shown
Visual Studio 2019 Debugging Productivity Tips 
Reattach to Process also works with debug sessions involving multiple processes. In this situation, Visual Studio attempts to find all processes it has been attached to with the same heuristics explained above. 
 

Process No-Side-Effect expression evaluation

 
Sometime when evaluating an expression in the Immediate or in the Watch window some state gets changed. This behavior is often undesirable, you don’t want to corrupt the state of your debugged program just because you needed to evaluate the value of an expression.
 
To avoid changing any state you can suffix your expression with, nse (No-Side-Effect). This possibility is illustrated by the animation below (watch the _State value changing or not in the Watch window),
 
Visual Studio 2019 Debugging Productivity Tips 
Here  nse is used in the Watch window. This sample is less trivial than the previous one because of the Refresh evaluation button in the SideEffectFct() watched item.
 
Visual Studio 2019 Debugging Productivity Tips 
 
No Side Effect expression evaluation in the Watch Window
 

Show Threads in Source

 
Debugging a multithreaded application is notoriously complex. Hopefully, the Show Threads in Source button can help a lot. It introduces marker icons in the editor gutter to keep track of the locations on which other threads are halted. This marker can be used to show the thread ids and eventually switch to another thread. Notice that a different marker glyph is shown if at least two threads are halted in the same location.
 
Visual Studio 2019 Debugging Productivity Tips 
More tips to debug multithreaded applications are available in this Microsoft documentation: Get started debugging multithreaded applications (C#, Visual Basic, C++)
Here is the source code of this small demo if you’d like to play with it,
  1. using System;  
  2. using System.Threading;  
  3. class Program {  
  4.     static void Main() {  
  5.         for (int i = 0; i < 5; i++) {  
  6.             // Avoid capturing a loop variable in the lambda below  
  7.             int j = i;  
  8.             // So 2 thread are blocked on '0' case  
  9.             if (j == 1) {  
  10.                 j = 0;  
  11.             }  
  12.             ThreadPool.QueueUserWorkItem(delegate {  
  13.                 Method(j);  
  14.             });  
  15.         }  
  16.         Thread.Sleep(60000);  
  17.     }  
  18.     static void Method(int id) {  
  19.         switch (id) {  
  20.             case 0:  
  21.                 Thread.Sleep(60000);  
  22.                 break;  
  23.             case 1:  
  24.                 Thread.Sleep(60000);  
  25.                 break;  
  26.             case 2:  
  27.                 Thread.Sleep(60000);  
  28.                 break;  
  29.             case 3:  
  30.                 Thread.Sleep(60000);  
  31.                 break;  
  32.             case 4:  
  33.                 Thread.Sleep(60000);  
  34.                 break;  
  35.         }  
  36.     }  

Decompile IL Code to Source Code that can be debugged 

 
Often we depend on some black-box components: assemblies for which we don’t have the source code.
 
However, when debugging a complex behavior it is convenient to observe and even debug the logic nested in black-boxes referenced. This is why since version 16.5 Visual Studio 2019 can generate some source code from compiled assemblies. Such source code is then debuggable. This feature is based on the OSS project ILSpy.
 
The decompilation menu can be proposed in the assembly right-click menu in the Modules window (as shown in the animation below) and in the Source Not Found or No Symbols Loaded dialogs.
 
Decompiling IL code to source code cannot be perfect because some source information is lost at compilation time. Hence this feature has a few limitations explained at the end of this official documentation: Generate source code from .NET assemblies while debugging.
 
Visual Studio 2019 Debugging Productivity Tips 
 

Conclusion

 
Visual Studio shines but it especially shines when it comes to debugging. Here I tried to select some tips that are both quite hidden but often useful, I hope they will help improve your productivity.
 
..... Keep Learning !!!!