Using DebuggerDisplay Attribute
The DebuggerDisplay attribute (System.Diagnostics.DebuggerDisplayAttribute
) controls how a class or field is displayed in the debugger variable windows. This attribute can be applied to:
Classes
Structs
Delegates
Enums
Fields
Interfaces
Properties
Assemblies
The DebuggerDisplay attribute has a single argument, which is a string to be displayed in the value column for instances of the type. This string can contain curly braces ({
and }
). Text within a pair of braces will be evaluated as a field, property or method.
In C# code, you can use a general expression between the curly braces. The expression has implicit access to the this
pointer for the current instance of the target type only. The expression has no access to aliases, locals, or pointers. If the expression references properties, attributes on those properties are not processed.
If a C# object has an overridden ToString()
, the debugger will call the override and show its result instead of the standard {<typeName>}
. Thus, if you have overridden ToString()
, you do not need to use DebuggerDisplay. If you use both, the DebuggerDisplay attribute takes precedence over the ToString()
override.
Whether the debugger evaluates this implicit ToString()
call depends on a user setting in the Options dialog box (Debugging category, General page). Visual Basic does not implement this implicit ToString()
evaluation.
The following table shows some possible uses of the DebuggerDisplay attribute and example outputs.
Attribute | Output (displayed in the Value column) |
---|---|
Used on a type with fields |
|
Parameter syntax can vary between languages, so use with care. |
|
Expression syntax varies between languages, so use with care. |
|
|
If last name is present—
—otherwise:
|
DebuggerDisplay can also accept named parameters.
Parameters | Purpose |
---|---|
|
These parameters affect the Name and Type columns of the variable windows. (They can be set to strings using the same syntax as the constructor.) Overusing these parameters (or using them improperly) can cause confusing output. |
|
Specifies the target type when the attribute is used at the assembly level. |
Example
The following code example shows how to use DebuggerDisplay, along with DebuggerBrowseable and DebuggerTypeProxy. When viewed in a debugger variables window, such as the Watch window, it produces an expansion that looks like this:
Name | Value | Type |
---|---|---|
Key |
"three" |
object {string} |
Value |
3 |
object {int} |
[DebuggerDisplay("{value}", Name = "{key}")]
internal class KeyValuePairs
{
private IDictionary dictionary;
private object key;
private object value;
public KeyValuePairs(IDictionary dictionary, object key, object value)
{
this.value = value;
this.key = key;
this.dictionary = dictionary;
}
public object Key
{
get { return key; }
set
{
object tempValue = dictionary[key];
dictionary.Remove(key);
key = value;
dictionary.Add(key, tempValue);
}
}
public object Value
{
get { return this.value; }
set
{
this.value = value;
dictionary[key] = this.value;
}
}
}
[DebuggerDisplay("Count = {hashtable.Count}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable
{
public Hashtable hashtable;
public MyHashtable()
{
hashtable = new Hashtable();
}
private class HashtableDebugView
{
private MyHashtable myhashtable;
public HashtableDebugView(MyHashtable myhashtable)
{
this.myhashtable = myhashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePairs[] Keys
{
get
{
KeyValuePairs[] keys = new KeyValuePairs[myhashtable.hashtable.Count];
int i = 0;
foreach (object key in myhashtable.hashtable.Keys)
{
keys[i] = new KeyValuePairs(myhashtable.hashtable, key, myhashtable.hashtable[key]);
i++;
}
return keys;
}
}
}
}
See Also
Reference
Using DebuggerTypeProxy Attribute
Concepts
Displaying Custom Data Types
Enhancing Debugging with the Debugger Display Attributes