Tom Goff's .Net Musings

Tidbits of information regarding .Net, C#, and SQL Server.

COTW: DebuggerHiddenAttribute Class

leave a comment »

The DebuggerHiddenAttribute[^] allows you to “hide” constructors, properties, and methods (herein referred to as class members) from the debugger. This means that if a class member has this attribute applied, then the debugger will not allow the user to step into in that class member. In addition, the debugger will not honor any break points in that class member. There is an small exception to this last point which I will describe later.

In the following console application, I have two methods in addition to Main:

using System;
using System.Diagnostics;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            SomeMethod();
            SomeOtherMethod();
        }

        static void SomeMethod() {
            for (Int32 i = 0; i < 1000; i++)
                Console.WriteLine(i);
        }

        static void SomeOtherMethod() {
            for (Int32 i = 1000; i < 2000; i++)
                Console.WriteLine(i);
        }

    }
}&#91;/sourcecode&#93;If I set a break point on each method (as shown below) and start debugging the application, then Visual Studio will stop execution on each method as they are called.

<a href="https://tjoe.files.wordpress.com/2007/10/debuggerhiddenattribute_1.png" title="DebuggerHiddenAttribute 1"><img src="https://tjoe.files.wordpress.com/2007/10/debuggerhiddenattribute_1.png" alt="DebuggerHiddenAttribute 1" /></a>

Clearly, this is the expected behavior. Now if we apply the DebuggerHiddenAttribute to one of the methods as shown here:

using System;
using System.Diagnostics;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            SomeMethod();
            SomeOtherMethod();
        }

        [DebuggerHidden]
        static void SomeMethod() {
            for (Int32 i = 0; i < 1000; i++)
                Console.WriteLine(i);
        }

        static void SomeOtherMethod() {
            for (Int32 i = 1000; i < 2000; i++)
                Console.WriteLine(i);
        }

    }
}&#91;/sourcecode&#93;Now when debugging, Visual Studio will disable the associated break point because the method is "hidden". You can also see below the reason that Visual Studio gives for disabling the break point.

<a href="https://tjoe.files.wordpress.com/2007/10/debuggerhiddenattribute_2.png" title="DebuggerHiddenAttribute 2"><img src="https://tjoe.files.wordpress.com/2007/10/debuggerhiddenattribute_2.png" alt="DebuggerHiddenAttribute 2" /></a>

Using this attribute can make debugging a bit easier. Looking at the code below, assume we set a break point on the PrintMessage call in the Main method and then want to step into the PrintMessage. Without the DebuggerHiddenAttribute on the GetFormat method, we would first step into the GetFormat method. We would then have to step out of GetFormat, then step into PrintMessage. In this example, we know that GetFormat is defect free and would not provide any useful information if it was debugged. So we can safely apply the DebuggerHiddenAttribute.

using System;
using System.Diagnostics;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            PrintMessage(GetFormat(), "Hello World");
        }

        [DebuggerHidden]
        static String GetFormat() {
            return "MyApp: {0}";
        }

        static void PrintMessage(String format,
            params Object[] args) {
            Console.WriteLine(format, args);
        }
    }
}

When and where to use this attribute can be tricky. If there was a defect in GetFormat (assuming there was more substantial code there), then we would not be able to debug it without removing the DebuggerHiddenAttribute.

In the tool-tip above, Visual Studio implies that if ‘Just My Code’ was disabled then we would be able to step into class members that have the DebuggerHiddenAttribute. Although, in my tests this was not the case. With ‘Just My Code’ disabled, Visual Studio shows the break point as enabled, but it is never hit and I cannot step into the “hidden” method.

If we explicitly tell the debugger to break, using the Debugger.Break[^] method, then Visual Studio will show the call to the method as the current statement. So in the following code, the call to SomeMethod in Main will be highlighted as the current statement and the code after the Debugger.Break call will not be executed yet. If you continue execution, then the code following the Debugger.Break call will be executed.

using System;
using System.Diagnostics;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            SomeMethod();
            SomeOtherMethod();
        }

        [DebuggerHidden]
        static void SomeMethod() {
            for (Int32 i = 0; i < 1000; i++)                 Console.WriteLine(i);             Debugger.Break();             Console.WriteLine("Some code after the break");         }         static void SomeOtherMethod() {             for (Int32 i = 1000; i < 2000; i++)                 Console.WriteLine(i);         }     } }[/sourcecode]In essence, the code is stopped at the point we called Debugger.Break. Since Visual Studio will not step into the "hidden" method, it moves up the stack to the place where the "hidden" method was called and displays that to the developer. Using the attribute can make debugger easier, but it can also hide important information if it's not used correctly. In general, I have found that simple properties (e.g. ones that simply get or set a field) benefit from this attribute.

Advertisements

Written by Tom

October 31, 2007 at 9:52 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: