Visual Studio Debugging Tips and Tricks

In the “Hour of Power” presentation at Tech.Ed, I showed how Visual Studio 2008 could be used for a better Debugging Experience. I tried to showcase 10 tips and mentioned that I’ll update the details of it in my blog. Here it is-

1. Debugging/Stepping into Framework code

With the launch of Visual Studio 2008, Microsoft have allowed developers to debug into the .NET Framework code.  This doesn’t happen by default however, and some settings need to be configured. The steps involved in configuring this for Visual Studio 2008 SP1 are:

  • Go to Tools->Options menu item and select Debugging/General on the left side of the dialog
  • Ensure that Enable .NET Framework source stepping option is checked
  • Ensure that Enable source server support option is checked
  • Select Debugging/Symbols on the left side of the dialog
  • Add the Symbol file location http://referencesource.microsoft.com/ symbols
  • Specify a cache symbol location directory

image

image

Once this is set, you will be able to step into .NET Framework code, set break points in it and look at values of private data members.  This not only provides the ability to debug the .NET Framework source code, it also provides a great reference implementation of classes.

2. Moving the Execution Point

When you are stepping through code in Visual Studio, the IDE displays the yellow arrow on the line of the code that it is about to execute.

image

This yellow arrow can be dragged and dropped on to any line that needs to be the execution line. Although, dragging the code forward can have some undesirable consequences if variable declaration and assignments are skipped, this feature can be very useful if used properly.

3. Step into Specific

In older Visual Studio versions, while stepping into code that has more than one function in the same line, the debugger ends up stepping into and out of each function. This can be very annoying at times. Visual Studio 2008 provides a functionality called Step Into Specific. This can be accessed from the context menu while debugging and allows you to step specifically into the function that you are interested in.

image

4. Step over properties and operators

Another annoying thing in older versions of Visual Studio was that the debugger would step into properties and operators. In a lot of cases, the properties were just wrappers for private data members, and stepping in and out of these properties was not particularly useful. One way to get around this problem is to decorate the property with the attribute DebuggerStepThrough. This would prevent the debugger from stepping into the property.

Visual Studio 2008 provides a much better debugging experience by providing an option called Step over properties and operators, that allows you to chose whether you would like to step into the property’s source code or not. This option can be set from the Options dialog –

image

It is also available in the context menu that pops up while debugging –

image 

5. Tracepoints

Visual Studio 2008 allows developers to easily add Tracepoints to look at values while debugging. This feature was also available in older versions of Visual Studio, but accessing this has just become a whole lot easier. So, what are Tracepoints? They are breakpoints, that allow you to execute something like printing a trace message on the Debug output window and optionally continue the execution without stopping when the break point has been hit. Trace points can be enabled from the debug context popup menu as shown below:

image

The variables whose values are to be displayed in the output window will have to be enclosed in curly brackets as shown in the screen shot below.

image

6. Conditional break points and trace points

Visual Studio also allows you to add conditional break points and trace points that are hit only when a certain condition is met. This can be easily accessed by right-clicking on a break point glyph

image

As shown in the menu options, you can specify the condition, hit count or even a filter for the break (or trace) point.

image 

7. The DebuggerDisplay attribute

When inspecting values in the debugger, Visual Studio does a great job of displaying the values just by hovering over a variable. But when you are inspecting objects, it is not always helpful as this example shows:

image

You will have to drill further into the object to see what the values are. To get over this problem the class Book can over ride the implementation of ToString. The Debugger will then display this value when it is inspected.

However, this is not the right way of doing it. The right way of doing it is to decorate the class with the DebuggerDisplay attribute as shown below –

 
[DebuggerDisplay("{ISBN}:{Title}")]
class Book
{
    public string ISBN { get; set; }

    public string Title
    {
        get { return title; }
        set { title = value; }
    }
    ...
}

Anything displayed within the curly brackets in the Attribute string will be evaluated – in this case the two properties ISBN and Title will be expanded as shown below –

image

This is definitely an improvement, but it still needs a bit of clean up as the two strings show quotes and null is being displayed when ISBN is not present. To accomplish this, the DebuggerDisplay attribute can be changed to –

 
[DebuggerDisplay("{ISBN == null ? \"\" : ISBN + \": \",nq} {Title.Substring(0, System.Math.Min(Title.Length, 33)) + (Title.Length > 33 ? \"…\" : \"\"), nq}")] 

class Book
{
   ...
}

The nq option within the curly brackets is for no quotes. In addition, expressions can also be evaluated within the braces. This is used to to display an empty string if ISBN is null and also to display elipsis when the length of the book title exceeds 33 characters. The net result is something like this –

image

8. The DebuggerBrowsable attribute

If we expand the first object in the array from the example above, we will notice that the Title is shown twice –

image

This happens because the lower case “title” is a private data member that the property “Title” uses. In effect, they are both the same, but if we have a class that has a lot of private data members that are wrapped by properties, a lot of redundant information will be displayed. To prevent certain data members to not be displayed, they will have to be decorated with a DebuggerBrowsable attribute with the DebuggerBrowsableState.Never set as shown below –

 9. The DebuggerTypeProxy attribute

When the variable values are displayed in the debugger, Visual Studio automatically evaluates all data members and properties and displays them on the screen. The DebeuggerTypeProxy attribute allows an alternate class to be used to determine which data members and properties are to be displayed. In the example shown below, the proxy class even calls a method, which is not evaluated by the debugger –

 
[DebuggerDisplay("{ISBN == null ? \"\" : ISBN + \": \",nq} {Title.Substring(0, System.Math.Min(Title.Length, 33)) + (Title.Length > 33 ? \"…\" : \"\"), nq}")] 
[DebuggerTypeProxy(typeof(ProxyView))]
class Book
{

    ...
}
class ProxyView
{
    Book book;
    public ProxyView(Book book)
    {
        this.book = book;
    }

    public string ConverToXml
    {
        get
        {
	    //Exposing method as a property	
            return book.ConvertToXml();
        }

    }

    public string Title
    {
        get
        {
            return book.Title;
        }
    }

    public string ISBN
    {
        get
        {
            return book.ISBN;
        } 
    }
}

10. The System.Diagnositcs Namespace

The System.Diagnostics class also contains a number of classes that can be used for printing out trace or debug information. The class Debug is used while compiling and running the application in Debug mode and the output is displayed in the Output window in VS 2008. The syntax for the Trace class is very similar to that of the Debug class with the exception that it will still be available while compiling and running the application in Release mode.

In the sample code shown below, a ConsoleTraceListener is added to redirect the traces to print the message to the console, rather than the output window

 
 
        Trace.Listeners.Clear();
        Trace.Listeners.Add(new ConsoleTraceListener());

        Trace.WriteLine("&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;<trace>&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;");
        Debug.WriteLine("[My Debug message]");

Type inference/Implicitly Typed local variables

One of the new features in C# 3.0 is Implicitly Typed local variables. In scripting languages like JavaScript, you can define a variable like this –

var x = “some value”;

You can now do the same thing with C# 3.0 and although some people may consider this feature to be nothing more than syntactic sugar or a declaration shortcut  for lazy programmers, it is needed for declaring anonymous types and while using LINQ (which I’ll cover in future posts).

C# uses type inference to automatically detect the type specified on the right hand side of the declaration. So, all these declarations are valid:

var myName = “Mahesh Krishnan”;
var myHeightInCms = 182;
var myWeightInKgs = 76.432;
var myPet = new Cat();
var dict = new Dictionary<int, string>();

var b = (ans == “Y“) ? true : false;

The main rule is that the variable has to be declared in one statement as shown above. Under the covers, C# substitutes  var with a string or an int or whatever type is specified on the right hand side of the declaration. This is done at compile time and as a result type safety is not compromised. When you use Visual Studio 2008, you will also notice that intellisense works correctly for the type used.

You cannot have an empty or null declaration

The C# compiler needs to know the type of variable it is creating. So an empty variable declaration or a variable declaration that is assigned to null is not allowed.

//Neither statements are valid
//
var uninitalized;

//var x = null;

Once a variable has been assigned, you cannot re-assign it to another type

In languages like JavaScript, you can assign an object to a variable and then re-assign another object of a different type to it. But in C#, this is not legal.

var myBooleanValue = true;           

//Cannot change types!
//myBooleanValue = “false”;

You cannot mix and match types

//Not allowed
var x = (myBooleanValue) ? true : “false”;

As I mentioned earlier, type inference is done during compile time and a statement as shown above is not supported as the type of x can only be determined at run time. As a result, this statement is not valid.

You cannot create an array of vars

Creating an array of var as shown below is not allowed:

//Not valid
//var[] arr = new int[] { 10, 20, 30 };

You can still assign an array to an array variable declared as a var as shown below –

 var arr = new int[] { 10, 20, 30 };

I will cover implicitly typed arrays in a later post.

Can only be used for local variables

One other major rule is that you cannot use var to declare member variables in a class. They are only allowed within a function body.

Use them wisely

Although, using var to declare a variable is a nice feature, use it wisely. Using it to declare known types such as integers and strings can make the code a bit unreadable. Another thing to avoid is using the keyword var as a variable. This is still allowed for backward compatibility, but you should avoid it at all costs.

(This is my second post on the new C# features. My first post on Property short cuts can be found here)

A Lap around VS2008

The first presentation at Tech Ed I went to was that of Tony Goodhew’s, who gave a presentation of what’s new in Microsoft Visual Studio 2008. I had already downloaded and played around with Beta 2 and didn’t find the presentation that useful, but this was obviously targeted at people who did not know much about the product and consisted of both features specific to VS 2008 and .NET 3.5. Some of the main points highlighted in the presentation were –

  • Support for the language advances
  • 400+ new features: This is more or less the same that were done for 2005
  • Web Designer enhancements: This includes the integration of the Expression web design panel into Visual studio and better CSS support. I quite liked the original Expression Web product and am quite happy with this integration
  • ASP .NET enhancements: Better XHMTL/JavaScript debugging/intellisense support as well as the integration of ASP.NET AJAX.
  • Multi-targeting support: This is basically the support for the different .NET versions within the one product. This means that you can build Apps for .NET 3.5, 3.0 and 2.0 using VS 2008. (Note: Although projects maybe backward compatible, the Solution file is not)
  • Client Application Services: This can be used to store Enterprise wide Personalization information/settings for applications.
  • WPF Support: Although you may still need Expression Blend to do things like animation and triggers visually, the product offers support for XAML apps.
  • WCF Support: Bunch of tools to support this and the ability to Create-Run-Test-Consume WCF services easily
  • Office 12 support
  • Local Data caching