Data Breakpoints and Pin-to-Frame – Debugger Updates in Rider 2020.2 EAP
Where and when does a value in our program change? And what’s the state of values in each iteration, when debugging recursive functions? Two good questions that Rider 2020.2 EAP helps answer, with Data Breakpoints and Pin-to-Frame!
"This can’t happen!" – Ever scratched your head when an object’s property is not what you would expect, and there doesn’t seem to be a good reason why that is?
Data breakpoints, sometimes called "watchpoints", are helpful when you need to focus on a particular object’s properties. You will typically use them in scenarios where you know what will change, but have no idea where the change comes from in your code base.
Here’s an example. There are 3 instances of
Account, and we’re adding a number of transactions to them. I would like to pause execution when the number of transactions in "Account 3" changes.
In the above example, we could have set a breakpoint inside of
List<T> (Rider does support debugging external libraries), or at a location where we know the value for the property will be changed. But that would pause the application for changes to all instances, not just for a specific one!
Instead of enduring constant, irrelevant breaks when there are multiple objects of the same type, you can use data breakpoints to pause when a property of a specific object changes, and then investigate further.
Data breakpoints are also useful when you encounter a heisenbug. It’s one of those bugs that happens when you’re not debugging, but never seems to occur when you look closer and add some breakpoints. Very often these are caused by timing issues or multi-threading, where the debugger slows down your application just enough to never see the issue. Instead of littering your code with conditional breakpoints, data breakpoints can help troubleshoot your code and only pause when a specific value changes.
Lastly, if you’re working with a large code base where there’s data access from many places in code, data breakpoints can help you figure out where a value is coming from, without having to set breakpoints everywhere a specific property is accessed.
Note that data breakpoints require .NET Core 3.0+ on Windows. Fields and properties of structs, and static fields and properties, are not supported right now.
A while ago, we introduced Pin-To-Top to show the info we’re interested in first. Much like
DebuggerDisplayAttribute, it lets you customize how objects in the debugger are shown. Except, no code changes are needed: you can change this on the fly.
In Rider 2020.2, we’re adding Pin-To-Frame, which lets you pin values across frames. You can pin parameters for a function, and see them in the list of stack frames. When debugging recursive functions, it lets you watch the state of values in different iterations.
Here’s an example. We’re calculating the total size of a directory structure by using recursion. When I first step into the
CalculateSize method, Pin-To-Frame is not used yet. I’ll then pin the
directory parameter and resume debugging. Note how the stack frames show the directory path for each recursion.
This will help you avoid having to always look through the variables or watches while debugging and stepping though recursive method calls.
Download Rider 2020.2 EAP now and give it a try! We’d love to hear what you think of these debugger improvements!