Tip 1: Use object exporter
During debugging, it’s often necessary to inspect the current object instances. if you’re working with arrays, this becomes tedious very quickly.
Oftentimes, it’s necessary to find a specific set of elements in the array. Object Exporter is for. It’s a Visual Studio extension, and you can install it manually from the Visual Studio Marketplace. Or you can install it from within Visual Studio via Tools -> Extensions and Updates. Please make sure that you select Online in the tree view to the left before you search for the extension.
It can export an object in different formats, namely JSON, XML, and C#. It’s also possible to export custom expressions. This is very helpful if you just want to export a subtree of an object graph.
Tip 2: Use ,nse to evaluate an expression without side effects
During debugging, you need to evaluate expressions all the time. As long as these expressions don’t change the state of the system, all is fine.
However, oftentimes, evaluating an expression causes a side effect.
For example, if you’re evaluating a property with lazy initialization, it’ll actually initialize that property in the context of the debugged code. This can lead to strange problems during debugging.
So if you want to watch o.MyProperty
, add the following to the Watch
window:
o.MyProperty, nse
This will execute the expression in a special sandbox, preventing any changes to the state of the debugged application.
Tip 3: Freeze multithreaded applications
Debugging multi-threaded applications can be a real pain, especially if multiple threads are executing the same code. Breakpoints will be hit by each thread, and single-stepping will switch between threads. It’s very easy to lose orientation and concentration like this. Wouldn’t it be great if it were possible to tell Visual Studio that you want to debug just this one thread and not switch to other threads that are currently executing the same code?
Well, turns out, there is a way to do this.
Open the Threads window via Debug -> Windows -> Threads. This window shows all threads of the current application. Double-clicking a thread switches to it. Right-clicking a thread shows different options, one of which is Freeze:
Threads window to freeze all threads for the current location except one. You can now debug this one thread and single-step through the code without thread switches interrupting your concentration. You can also set breakpoints and be sure they’ll be hit for the correct thread.
If you want to continue running the program after you’ve debugged the code in the thread, you should unfreeze—or Thaw—the other threads so they can perform their work as well.
Tip 4: Use Object ID
Object IDs are a feature of the Visual Studio Debugger that has several helpful use cases.
One such use case is that object IDs basically allow you to make a certain object instance globally available during debugging. This lets you compare it to other instances at a code location where the instance wouldn’t be available otherwise.
Another use case is to compare object identities. Imagine a scenario where you’re debugging an app that uses a dependency injection container. This app contains two classes that are receiving an instance of a service class via their constructors. The service instance resembles the way by which the two classes can communicate with each other. However, this coordination doesn’t work for some reason. One reason for this issue could be that the two classes aren’t receiving the same instance of the service class.
Object ID can easily identify this issue.
To use it, add a breakpoint at the constructors of the two classes. When the breakpoint gets hit in the first class, right-click the service instance in the Locals window and choose Make Object ID. When the breakpoint in the second class gets hit, check if the instance shows the object ID. If so, they’re the exact same instance.
Tip 5: Make sure you’re getting stack traces
When you catch an exception and rethrow it, never ever use throw ex;
. Instead, use throw;
. The first variant loses the original stack trace and therefore masks the original error location.
my thanks to this great article:
https://raygun.com/blog/dot-net-debugging/