Tracking down those pesky flaws in a piece of code is, in my humble opinion, the most challenging part of software development. Thankfully we have a top-notch debugger built into Visual Studio. Unfortunately, the debugger is one of the features of Visual Studio that I am the least proficient with. I know how to set a breakpoint and take a look at the values of my local variables when that breakpoint is reached, but beyond that I'm pretty much clue-less. Well, I was lucky enough to attend John Cunningham's talk at PDC last week and learned quite a few valuable tips that enhanced my debugging abilities.
1. Step over simple properties*. The Visual Studio debugger now allows you to automatically step over simple properties (your getters and setters) when stepping through your code. This feature is automatically turned on with VS2008 SP1, so you don't need to do anything at all to get this functionality. However, since there are times when you might want to step into your properties, you can disable this feature in Tools | Options | Debugging | General and deselecting the Step over properties and operators checkbox.
Alternatively, when debugging you can right-click in your code and deselect the Step over properties and operators option in the context menu. One final option available to you for more fine-tuned control is the Step Into Specific menu, which appears in your context menu when debugging. This menu contains all of the target methods that the line of code you are on can invoke, and allows you to select them individually so that you can step into them and debug them as needed.
*This tip requires Visual Studio 2008 Service Pack 1 (or a later version).
2. Setting Tracepoints. Most of us know and love breakpoints. They're those awesome little red dots that you place next to a line of code to halt execution so you can examine the current state of the application. But there is this cool new feature introduced in Visual Studio 2008 that allows you to perform some action automatically when that line of code is reached . This feature is called a tracepoint.
Tracepoints weren't really introduced in Visual Studio 2008; they are also available in VS 2005. In fact, they were only distinguished from breakpoints (with a new name and a spot in the context menu) in the newer version. Those of you who haven't yet upgraded can get this functionality too. But I digress...
To insert a tracepoint, simply right-click on a line of code and select Breakpoint | Insert Tracepoint.
This will launch a dialogue from which you can define a behavior for that tracepoint. First, you can print any message you want. This is handy if you are an old-school developer who loves to use Console.Writeline() to output variable values, but with this method you do not have to dirty up your code. You can also associate a macro with the tracepoint and you can decide whether or not you want the code to halt at the tracepoint (at which time it becomes a breakpoint?) by selecting or deselecting the Continue execution checkbox.
Finally, you'll notice that when using a tracepoint you get a red diamond indicator next to the line of code instead of the typical red circle associated with breakpoints.
When the code execution reaches the tracepoint, the debugger will print your message, run your macro, and/or halt execution, depending on the preferences you set.
For those of you using Visual Studio 2005, you can get this same functionality by setting a breakpoint, right-clicking on it and selecting the "When hit..." option from the context menu.
3. Conditional Breakpoints. Sometimes in order to track down a bug or verify your code's behavior, you need the debugger to break on a certain line of code, but only if a certain condition is met. I don't know how many times I've had a breakpoint inside a foreach loop and been forced to hit the Continue button in Visual Studio over and over until the variable I was interested in finally had a certain value. Imagine how delighted I was when I learned how to set conditional breakpoints so that the code would simply continue chugging along until that condition was met.
To set a condition on your breakpoint, right-click on it and select Condition... You will be greeted with a dialogue which allows you to set an expression as your condition, and two radio buttons which specify whether to break when the expression is satisfied (Is True) or when the value of the expression has changed (Has Changed).
Notice now that the breakpoint contains a white "plus" sign in the middle of it, indicating that it is a conditional break point.
Another condition you can set is a hit count. You set this by right-clicking on your breakpoint and selecting the Hit Count... option. Again you'll be greeted with a dialogue that asks you to specify a condition which will cause the debugger to halt code execution.
You are given 4 options: Break Always, Break when hit count is equal to <insert value>, Break when hit count is a multiple of <insert value>, and Break when hit count is greater than or equal to <insert value>. A "hit" occurs only when the other conditions for that breakpoint are met. So if I have the condition "i % 2 == 0" on a breakpoint inside a for loop and a hit count set as "Break when hit count is a multiple of 2" the debugger will break when i = 2, 6, 10, 14, 18, etc...
4. Enable .NET reference support. Earlier this year, Microsoft announced that it would make the .NET Framework source code available to developers for debugging support. While this was great news for developers, there were a few steps that had to be taken in order to make the source code available in Visual Studio. You see, you can't just go download the source and browse through it; instead, you must reference the symbol files from Microsoft's source server and download them when you are ready to step into some framework code. Shawn Burke posted some detailed instructions on how to do this in Visual Studio 2008.
Now, with Visual Studio 2008 SP1 you can skip all of those steps and set a single option to get .NET reference support. Simply go to Tools | Options | Debugging | General and select the Enable .NET Framework Source Stepping checkbox. When you hit OK, Visual Studio will download the .NET Framework symbols to your symbol cache. If you want to change the default location of your symbol cache, go to Tools | Options | Debugging | Symbols.
Now whenever you want to step into a .NET Framework method, you can do so just like you do with the methods in your project. In the picture below, I hit F11 to step into the Trim() method of the System.String class.