Article Author: Saurabh Nandu
Introduction
Debugging is an essential activity carried out by any developer while writing applications. In fact one of the core reasons we use IDEs like Visual Studio is that they provide rich debugging facilities that helps speed development and cuts time spent finding and fixing bugs. Visual Studio .NET 2003 saw the introduction of end-to-end debugging features for web applications, where you could start debugging from your web application, step into your business logic and finally step into SQL Server’s stored procedures. In Visual Studio 2005 Microsoft continues enhancements adding new features for debugging that will help significantly cut debugging time, ultimately speeding up development.
This article will look at the following features in Visual Studio 2005:
- Edit and Continue
- Debugging Visualizers
- Data Tips
- Exception Assistant
- Just My Code debugging
- Tracepoints
- Object Identity while debugging
System Requirements
This article is based on the Beta 2 release of Visual Studio 2005 from Microsoft. Basic knowledge of debugging .NET applications is required to best understand this article. You’ll also need SQL Server 2000 with the Northwind database.
Installing and Compiling the Sample Code
The sample download for this article contains three VS.NET solutions:
- EditCountinue
- DataApp
- JMC
You will have to edit the value of DataApp.Properties.Settings.NorthwindConnectionString in the app.config file to point to SQL Server with the Northwind database in your environment for the DataApp solution.
You can open the solution files in Visual Studio 2005 to view each of the samples. These samples are used in the following sections to demonstrate the functionality of the debugger.
Edit and Continue
There are times when you are debugging a large chunk of code or a code block nested deep in the debugging hierarchy and you encounter a small mistake like a variable has been set to an incorrect value – at times like this it would be convenient if we could make the change right there while debugging and then continue execution of the code. In Visual Studio .NET 2003 one had to stop debugging, make the change, recompile, start debugging again and reach to the point of error – in short a lot of time gets wasted to fix small errors. Visual Studio 2005 now supports Edit and Continue in the debugger, which means that in such cases you can directly make the change in code while debugging and continue to debug. The debugger performs a compile in the background and continues execution with the new changes.
In the early alphas of Visual Studio 2005, Edit and Continue was only going to be supported by VB.NET, but due to heavy demand for this feature from the C# developer community the C# product team at Microsoft enabled this feature for C# as well.
To test drive this feature, start Visual Studio 2005 and open the EditContinue solution to load a small Windows form application I have created. If you open Form1 in the Design Window from Solution Explorer you will see a form similar to Figure 1.

Figure 1. Sample application to test Edit and Continue
As you can see from Figure 1 it’s a simple Windows form with a label, a textbox and a button. When the user enters their name and clicks the button a welcome message is displayed to the user. Below is the code snippet for the button’s click event handling method.
private void button1_Click(object sender, EventArgs e)
{ //Show welcome message MessageBox.Show("Welcome textbox1.Text to Edit and Continue.");
}
If you look closely at the code above you will find that I have made a mistake, and instead of concatenating the text from the textbox1 , I have included the textbox1.Text variable in the string leading to the wrong message being displayed as shown in Figure 2.

Figure 2. An incorrect welcome message
Let’s fix this error but using Edit and Continue. You should press F7 while Form1 is selected in the Design Window to switch to Code View , and place a break point on line 20 which has code to display the MessageBox. Now start debugging the application by pressing F5 .
Enter your name in the textbox and click on the Click Me button, the IDE will break on line 20 highlighting it in yellow. Change the code as shown in the listing below to fix the bug:
private void button1_Click(object sender, EventArgs e)
{ // Fixed welcome message MessageBox.Show("Welcome " + textbox1.Text +" to Edit and Continue.");
}
Once you make the change in the code press F5 to continue debugging and the correct welcome message will be displayed as shown in Figure 3 (of course with the name you have provided).

Figure 3. The correct welcome message
What the IDE did as you changed the code is that it recompiled the application in the background to include the changes you have made and then continued debugging. This way you can have a richer debugging experience while the compiler takes the hit to perform background recompile of your code.
Although I have taken a trivial example, it shows how useful Edit and Continue can be while fixing code errors.
Most changes to code inside the current executing method body are allowed. There are some restrictions on code changes allowed – if you make a change that is not allowed the IDE will underline the changed code with a purple wavy line to indicate that you need a recompile to make the changes take effect. There is a link in the related links for this article that provides details of all unsupported edits for C# and VB.NET. Some examples of the types of changes not allowed include changing a class name, adding new methods and renaming a method.
Debugging Visualizers
One of the most frustrating experiences while debugging complex objects is the difficulty of visualizing the value(s) of the object. For example if you have set a breakpoint on a DataSet object and want to visualize the different DataTables it holds and further drill down into the DataTable to see the actual rows returned – its just not possible using Visual Studio .NET 2003. In Visual Studio .NET 2003 one would have to observe the DataSet object in the Autos/Locals window and keep expanding its internal private variables to hunt for relevant DataTable instances. The hunting for the data contained within those tables would be painful, it might turn out to be easier to just dump the DataSet to an XML file and observe its values.
Visual Studio 2005 solves this problem by introducing the concept of Debugging Visualizers. Debugging Visualizers are visual aids that help you visualize the values of your objects better while debugging and provide a natural view into the variable. The current Beta2 IDE ships with 3 Visualizers for strings – Text, XML and HTML – as well as a DataSet Visualizer that works with DataSet , DataView and DataTable objects. Microsoft plans to make more Visualizers available for download at a later point after the release of Visual Studio 2005.
Debugging Visualizers can be accessed from Data Tips (explained below) as well as from any of the debugger windows like Autos , Locals , Watch and QuickWatch . You can click on the magnifying glass icon (see Figure 4) to select the various available visualizers for your object. The debugger then depends on the Visualizer to display the data in an appropriate form. For example the XML Visualizer renders the XML in an instance of Internet Explorer.

Figure 4. Select a visualizer by clicking on the magnifying glass icon
Figure 4 above shows you how you can click on the magnifying glass icon in the Autos window to select a relevant Visualizer. Figure 5 below displays contents from a DataSet object filled from the Northwind database’s Orders table. The screenshot shows that I have invoked this visualizer by clicking on the magnifying glass icon displayed as a DataTip in the code editor. If the DataSet contains multiple tables you can switch between them from the Table dropdown displayed in the Visualizer.
This makes it very easy to debug the values returned by your TSQL queries or stored procedures.

Figure 5. Debugging using a Visualizer that displays the values contained within a Dataset.
Data Tips
Data Tips are useful tool tips that are displayed in the code editor when you hover your mouse over an active variable (i.e. a variable accessible in current context) while you have broken code execution in debug mode. This is not new, Visual Studio .NET 2003 contained Data Tips but they displayed very little information about the variables. In Visual Studio 2005 Data Tips have been greatly enhanced to display a total drill down view into the object and its relevant values.
To view a Data Tip, start Visual Studio 2005 and switch to Code View and put a break point on any of the statements in your method. For this example I have started the EditContinue solution mentioned above with a break point on line 20. Press F5 to start debugging the application. Once the form shows up enter your name and click the Click Me button. Once the IDE breaks, hover your mouse pointer over the textbox1 variable and you will be shown the Data Tip as shown in Figure 6. You will notice that first the tip displays the most relevant value you might want to see for the variable highlighted. Since it’s a TextBox control the most relevant property is Text , hence the Data Tip first displays the value of the Text property which is Saurabh (my name I had entered in the textbox). If you hover your mouse over the little plus + icon on the tip next to the variable name textbox1 you can see the list of public properties for the textbox and their values.

Figure 6. Data Tip showing the details of the TextBox
In Figure 6 you will also observe that there is a base {System.Windows.Forms.TextBoxBase} listing. This shows the base class for the TextBox control, if you hover your mouse over the base it will open a new tip displaying the public properties of the base class. In this way you can keep going up the inheritance hierarchy of objects until you reach the base of all classes in .NET System.Object .
If the Data tip is covering your source code view you can press the Control key to temporarily make the Data Tip transparent so you can view the code below, release the Control key and the tip will turn opaque. Data Tips are also integrated with the Edit and Continue feature to edit any of the properties, right-click on property name to bring up the context menu and select Edit Value as shown in Figure 7.

Figure 7. Edit values of an object directly from the Data Tip
On selecting Edit Value you will be able to directly edit the property value within the Data Tip. Once you finish editing press Enter to confirm the changes. At this point the Edit and Continue debugging feature will kick in and recompile the application to reflect the change of the property. In continuation with the example, right-click on the Text property of the Data Tip that displays for textbox1 and select Edit Value from the context menu. Change the name to some other name and press Enter . Now press F5 to continue execution of the code. You will find that the messagebox displaying the welcome message contains the updated value.
Exception Assistant
In Visual Studio .NET 2003 while debugging code when an unhandled runtime exception would occur generally the IDE would show an Exception Dialog and ask you if you want to break the execution or continue. This was not particularly useful since it did not give you any details of the exact exception that occurred, nor did it tell you how to fix this error.
Visual Studio 2005 now provides a developer friendly exception assistant that shows up whenever an unhandled (i.e. there is no try-catch block to catch the exception) runtime exception occurs (see Figure 8).

Figure 8. Exception Assistant
The Exception Assistant in Figure 8 displays a SqlException that has occurred due to a connection timeout. Under the Troubleshooting tips a general description is provided, but in the future this section will provide more content that describes the reasons why this exception gets raised and solutions to prevent it. Under the Actions section you can either copy the exception to the clipboard so it can be pasted in notepad/editor to view the details of the exception or you can click View Detail to view a dialog as shown in Figure 9 that provides the details of the exception. You can expand the exception details to dig deeper into the exception message that was raised.

Figure 9. View Detail dialog that displays the details of the exception
Just My Code Debugging,,
Debugging a large application with multiple projects can be challenging task. Often we like to just focus on debugging code written by us rather than step through code written by our peers. Many times we use Data Access Block projects (like the Data Access Block part of the Enterprise Library released by Microsoft) which have been tested to be stable and bug free. While using these projects in our solution we do not want to spend time stepping into the Data Access Block code since its deemed stable. In Visual Studio .NET 2003 the general solution would be to either place break points at the end of each call to these libraries that we did not want to debug and use F5 to jump over the call or to remember to use F10 to Step Over the call to the library. In short it is a frustrating experience while debugging large applications.
Visual Studio 2005 introduces the concept of Just My Code (JMC) debugging to enable developers to customize their debugging experiences and control what parts of code they Step Into . JMC works by identifying code as user code and non-user code. If JMC is enabled the debugger will never stop in code marked as non-user code.
JMC is controlled by two aspects when the functionality is turned on (it’s turned on by default in Visual Studio 2005 Beta2). In the first case if any project is built in release mode (i.e. there are no pdb files available for the project) the debugger marks it as non-user code and chooses to ignore this code and jump over it. So suppose one of the class library projects in your solution is built in release mode with no pdb file available then the IDE will never step into any of the functions invoked in this library.
Secondly you can apply the DebuggerNonUserCodeAttribute ( System.Diagnostics namespace) attribute to mark classes, structs, methods or properties as non-user code making the debugger jump over it. You can also use the DebuggerHiddenAttribute to hide code from the debugger, this would even work if the JMC functionality is turned off.
Note: Many times even if you change the mode of the project from Debug to Release, the pdb file is not deleted from the Bin folder of the project. Hence the IDE will continue to step through the code. You might have to manually delete the pdb file to ensure JMC kicks into effect.
The code listing below shows a simple console application with two static methods UserCode() and NonUserCode() . You will notice that the method NonUserCode() is affixed with the DebuggerNonUserCode attribute. Applying this attribute on any methods makes the debugger jump over this method. You can open JMC , a Console Application project in Visual Studio 2005, and place a breakpoint on line 9 (also indicated with a comment). Now press F5 to debug this application, it will break on line 9 (due to the break point). Keep pressing F11 to Step InTo the methods. You will realize that the debugger steps into the UserCode() method but jumps over the NonUserCode() method and finally gets back into the UserCode() method just to confirm that you can continue debugging the remaining lines of code.
using System;
using System.Diagnostics;
class Program
{ static void Main(string[] args) { // Step into F11 from here UserCode();// Place break point on this line NonUserCode(); UserCode(); } static void UserCode() { Console.WriteLine("This is a call from user Code"); } // Attribute to indicate the Debugger to jump // over this method [DebuggerNonUserCode] static void NonUserCode() { Console.WriteLine("This is a call fron Non User Code"); }
}
As seen from the example above you can mark up classes, methods or properties with the DebuggerNonUserCode attribute and the debugger will jump over these while debugging when the JMC feature is enabled.
Another way specific to C#, is to utilize the line hidden directive. The line directive has a similar syntax to the region / end region directive that can be used to mark blocks of regions in source code. Using the line hidden directive all the lines of code below the directive are hidden from the debugger, until the debugger encounters a line default directive. You can use this to mark blocks of coding inside a method that you want to skip while debugging.
The code listing below is very similar to the previous example, but instead of using the attribute I have used the line hidden directive to hide the Console.WriteLine call in the NonUserCode() method. You can make the changes to the JMC project as shown below. Now you debug this application and step through it you will realize that this time the debugger steps into the NonUserCode() method but it jumps over the line wrapped in the line directive.
using System;
using System.Diagnostics;
class Program
{ static void Main(string[] args) { // Step into F11 from here UserCode();// Put break point here NonUserCode(); UserCode(); } static void UserCode() { Console.WriteLine("This is a call from user Code"); } static void NonUserCode() { // line hidden directive to indicate the Debugger to jump // over this line #line hidden Console.WriteLine("This is a call fron Non User Code"); // End of line hidden #line default }
}
The line directive is very useful to mark chunks of code to be hidden from the debugger. Although I must bring to your attention that it might not behave as you might expect. For example, instead of wrapping line 24, if you wrap line 10 with the line directive (modified Main() method shown below). Now if you start debugging the debugger will jump to line 11 (call to NonUserCode() ) but it will enter inside the NonUserCode() method. This is because the line hidden directive only indicates the debugger to jump the lines marked, not the functions, properties they invoke.
static void Main(string[] args)
{ // Step into F11 from here UserCode(); #line hidden NonUserCode(); #line default UserCode();
}
Displaying Public and Private Properties
In Visual Studio.NET 2003 when you added a variable to the Quick Watch or any such debugging window to view its details and you expanded the object, you were presented by default all the values of the object including the private field values and the public ones. This made the list of values very large and ugly. Also it was hard to find the relevant property that you wanted to check, lost in this large list of values. In Visual Studio 2005 only relevant public properties are displayed at first (see Figure 6). If you wish you can expand the non-public members to view non-public fields similarly you can expand the static members to view details of any static fields. But for most uses the default view is fantastic giving you precisely the values you want to check.
Besides implementing this enhancement in Data Tips it’s also been implemented in other debugging windows like Autos , Locals and Watch . Hence all these windows now only display the key properties by default.
This feature of only showing relevant entries in the debugging windows and Data Tips is also controlled by JMC. If you wish to view all the fields of a variable like Visual Studio.NET 2003 you can turn off JMC by selecting Tools menu → Options . In the Options Dialog select Debugging and uncheck Enable Just My Code (Managed Only) and click OK to apply the settings.
Tracepoints
Tracepoints are a feature expansion of the existing breakpoint functionality. Traditionally when we set a breakpoint and start debugging, the debugger process breaks at the breakpoint. Tracepoints add the ability to execute custom actions when the debugger passes a Tracepoint. You can choose to direct the debugger not to break on a Tracepoint, but just execute your custom action which could be to print a message (including the value of the variable) or to invoke a macro for larger actions.
Many times while debugging Windows forms application I end up writing several MessageBox.Show() or Console.WriteLine() statements that just print the values of the variable/condition I am trying to debug. The flip point of this approach is that after I finish debugging I need to make sure I remove/comment these lines – which is an ugly solution. The other way is to use the Trace class from the System.Diagostics namespace to write trace messages to the console screen or trace file. This is a good option but it can clutter up your code if used to heavily.
Visual Studio 2005 now introduces Tracepoints, which allow you to either print values to the Output Window or execute custom macros when the debugger passes through them giving you an alternative way of printing variable values without cluttering your code.
To add a Tracepoint open the source file in Code View , right-click the line where you want to add a Tracepoint and select Breakpoint → Tracepoint from the context menu. A When Breakpoint Is Hit dialog is displayed (see Figure 10), this dialog provides you with 3 options:
- Print a Message – Allows you to print a message to the Output Window of the IDE. Visual Studio 2005 defines some special keywords like $FUNCTION that can be used to print the relevant values as explained on the dialog screen. You can replace this message with your own message placing variables whose value you want to print inside braces. So for example to print the value of the Text property of a TextBox variable would be: The value of the TextBox is : {textbox1.Text}
- Run a macro – Macros are scripts that can be run to automate tasks within the Visual Studio IDE. You can record your own macros first and then select it from here. How to record macros is out of the scope of this article, you can find more information on this in the related links section.
- Continue Execution – If this checkbox is selected the debugger will not break at the Tracepoint, it will just perform the custom action and proceed.

Figure 10. Adding a new Tracepoint
When you press OK on the When Breakpoint is Hit dialog it sets a diamond icon to indicate a Tracepoint (see Figure 11). Existing breakpoints can also be converted into Tracepoints by right-clicking on the breakpoint and selecting When Hit from the context menu.

Figure 11. Converting a breakpoint into a Tracepoint
Object Identity While Debugging
Object Identity is a new concept of providing an alias to an object while debugging, this alias is active throughout the debugging session till the variable is in scope. You can then directly call the variable from anywhere in the IDE while debugging with its alias reference.
Suppose you are debugging a complex structured object like a DataSet or a HashTable which is composed of many smaller objects, now if you want to track the value of a particular object inside this DataSet or HashTable it’s a difficult task to achieve in Visual Studio.NET 2003. In Visual Studio 2005 you can use the Object Identity functionality to tag any object (could be buried levels underneath another object) and then you can recall the value of this object at any time using its tag/alias. You don’t need to keep digging into the parent object to find change in values.
You can use Object Identity from either DataTips (see Make Object ID from Figure 7) or from any of the debugger windows like Autos , Locals Watch etc.
For example I have created a Windows forms application ( DataApp ) that fills a Typed DataSet and binds it to the DataGridView . I have filled the DataSet with the Orders and OrderDetails table from the Northwind database that installs with SQL Server. I put a breakpoint after the DataSet is filled with records and view the Autos window. I expand the this.northwidnDataSet entry for my Typed DataSet variable to view its details as shown in Figure 12. Next, I right-click on the Orders table in the Autos window to bring up the context menu and select Make Object ID .

Figure 12. Adding an Object ID for the Orders variable
This action creates an alias to the Orders variable with the name 1# . This alias {1#} is shown in the Autos window besides the {Orders} value in Figure 13. This alias is the Object ID for the Orders variable and can be accessed from anywhere in the application until the DataSet variable is in scope. In fact you can utilize Edit and Continue facilities of the debugger to assign the alias to a DataGridView at debug time and the changes will take effect.

Figure 13. Object ID 1# added to the Orders table
Figure 14 shows how to invoke the Count property of the Rows collection to get the count of rows in the table in the Immediate Window . You will notice that the alias 1# needs to be explicitly type-casted into the type DataApp.NorthwidDataSet.OrdersDataTable before being used.

Figure 14. Displaying the Count of rows using the Object ID alias
This would be an ideal case where there are multiple methods manipulating the values inside the Orders data table and you can simply use the alias to quickly check the changes made to it.
Remember that Object ID’s are valid while the debugging session lasts; once the debugging session ends, all the Object ID’s are lost.
Other New Features
Besides these, there have been other changes to the debugging experience like the addition of the process window for multi-process debugging, additions to support CLR debugging inside SQL Server 2005 and support for debugging code at runtime – Object Test Bench (which needs an article itself).
Conclusion
In this article I have provided an overview of some of the major new changes to the debugging experience provided by Visual Studio 2005. These changes will help developers cut time debugging plus provide additional tools for debugging complex applications. Edit and Continue helps you to quickly fix bugs and cut debugging time; Debugging Visulizers and Data Tips help you visualize complex objects better; Just My Code debugging lets you concentrate on debugging your code only; Tracepoints provide you with the ability to execute custom actions – generally print values while debugging; and finally Object ID’s help you quickly refer to nested objects while debugging.
Powered with this functionality a developer would definitely be spending more time writing code rather than debugging it.

