使用调试器显示特性增强调试
调试器显示特性允许类型的开发人员(他们指定并且最理解该类型的运行时行为)同时指定该类型显示在调试器中时的外观。 此外,用户无需知道源代码即可在程序集级别应用提供 Target 属性的调试器显示特性。 DebuggerDisplayAttribute 特性控制如何在调试器变量窗口中显示类型或成员。 DebuggerBrowsableAttribute 特性确定是否以及如何在调试器变量窗口中显示某个字段或属性。 DebuggerTypeProxyAttribute 特性指定某个类型的替代类型或代理,并更改在调试器窗口中显示该类型的方式。 在查看具有代理或替代类型的变量时,该代理在调试器显示窗口中代表原始类型。调试器变量窗口仅显示代理类型的公共成员。 不显示私有成员。
使用 DebuggerDisplayAttribute
DebuggerDisplayAttribute 构造函数具有单个参数:要在类型实例的值列中显示的字符串。 此字符串可以包含大括号({ 和 })。 大括号对中的文本按表达式进行求值。 例如,当选择加号 (+) 展开 MyHashtable 的实例的调试器显示时,下面的 C# 代码导致“Count = 4”被显示出来。
[DebuggerDisplay("Count = {count}")]
class MyHashtable
{
public int count = 4;
}
应用于表达式中引用的属性的特性未被处理。 对于 C# 编译器,允许使用常规表达式,这些表达式只能对目标类型的当前实例的 this 引用进行隐式访问。 该表达式是受限制的,不存在对别名、局部变量或指针的访问。 在 C# 代码中,可以在大括号之间使用常规表达式,它们只能对目标类型的当前实例的 this 指针进行隐式访问。
例如,如果 C# 对象重写了 ToString(),则调试器将调用该重写,并显示其结果而不是显示标准的 {<typeName>}.。因此,如果重写了 ToString(),则不需要使用 DebuggerDisplayAttribute。 在同时使用这两者时,DebuggerDisplayAttribute 特性将优先于 ToString() 重写。
使用 DebuggerBrowsableAttribute
将 DebuggerBrowsableAttribute 应用于某个字段或属性,以指定如何在调试器窗口中显示该字段或属性。 此特性的构造函数采用 DebuggerBrowsableState 枚举值之一,该值指定下列状态之一:
Never 指示数据窗口中不显示该成员。 例如,将此值用于某字段的 DebuggerBrowsableAttribute 将从层次结构中移除该字段;当您通过单击类型实例的加号 (+) 来展开封闭类型时,不会显示该字段。
Collapsed 指示将显示成员但默认情况下不展开。 这是默认行为。
RootHidden 指示不显示该成员自身,但是如果它是数组或集合,则显示其构成对象。
注意 |
---|
.NET Framework 2.0 版中的 Visual Basic 不支持 DebuggerBrowsableAttribute。 |
下面的代码示例演示如何使用 DebuggerBrowsableAttribute 阻止它后面的属性出现在类的调试窗口中。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";
使用 DebuggerTypeProxy
在需要显著或根本性地更改类型的调试视图但是不更改类型自身时,应使用 DebuggerTypeProxyAttribute 特性。 DebuggerTypeProxyAttribute 特性用于指定类型的显示代理,允许开发人员定制类型的视图。 此特性与 DebuggerDisplayAttribute 类似,可以在程序集级别使用,在这种情况下,Target 属性指定将为其使用代理的类型。 建议的用法是此特性指定一个私有嵌套类型,它出现在该特性所应用到的类型中。 显示类型时,支持类型查看器的表达式计算器将对此特性进行检查。 如果找到该特性,表达式计算器就会替换应用该特性的类型的显示代理类型。
如果存在 DebuggerTypeProxyAttribute,调试器变量窗口将仅显示代理类型的公共成员, 而不会显示私有成员。 特性增强的视图不会更改数据窗口的行为。
为了避免不必要的性能损失,显示代理的特性将在展开对象(可通过用户在数据窗口中单击类型旁的加号 (+),或通过应用 DebuggerBrowsableAttribute 特性)之后处理。 因此,建议不要将任何特性应用于显示类型。 特性可以并且应该在显示类型的代码体中应用。
下面的代码示例演示如何使用 DebuggerTypeProxyAttribute 指定将用作调试器显示代理的类型。
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
private const string TestString =
"This should not appear in the debug window.";
internal class HashtableDebugView
{
private Hashtable hashtable;
public const string TestStringProxy =
"This should appear in the debug window.";
// The constructor for the type proxy class must have a
// constructor that takes the target type as a parameter.
public HashtableDebugView(Hashtable hashtable)
{
this.hashtable = hashtable;
}
}
}
示例
说明
可以在 Visual Studio 2005 中查看下面的代码示例以确定应用 DebuggerDisplayAttribute、DebuggerBrowsableAttribute 和 DebuggerTypeProxyAttribute 特性的结果。
代码
Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Reflection
Class DebugViewTest
' The following constant will appear in the debug window for DebugViewTest.
Const TabString As String = " "
' The following DebuggerBrowsableAttribute prevents the property following it
' from appearing in the debug window for the class.
<DebuggerBrowsable(DebuggerBrowsableState.Never)> _
Public Shared y As String = "Test String"
Shared Sub Main()
Dim myHashTable As New MyHashtable()
myHashTable.Add("one", 1)
myHashTable.Add("two", 2)
Console.WriteLine(myHashTable.ToString())
Console.WriteLine("In Main.")
End Sub 'Main
End Class 'DebugViewTest
<DebuggerDisplay("{value}", Name := "{key}")> _
Friend Class KeyValuePairs
Private dictionary As IDictionary
Private key As Object
Private value As Object
Public Sub New(ByVal dictionary As IDictionary, ByVal key As Object, ByVal value As Object)
Me.value = value
Me.key = key
Me.dictionary = dictionary
End Sub 'New
End Class 'KeyValuePairs
<DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(GetType(MyHashtable.HashtableDebugView))> _
Class MyHashtable
Inherits Hashtable
Private Const TestString As String = "This should not appear in the debug window."
Friend Class HashtableDebugView
Private hashtable As Hashtable
Public Shared TestString As String = "This should appear in the debug window."
Public Sub New(ByVal hashtable As Hashtable)
Me.hashtable = hashtable
End Sub 'New
<DebuggerBrowsable(DebuggerBrowsableState.RootHidden)> _
ReadOnly Property Keys as KeyValuePairs()
Get
Dim nkeys(hashtable.Count) as KeyValuePairs
Dim i as Integer = 0
For Each key As Object In hashtable.Keys
nkeys(i) = New KeyValuePairs(hashtable, key, hashtable(key))
i = i + 1
Next
Return nkeys
End Get
End Property
End Class 'HashtableDebugView
End Class 'MyHashtable
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
class DebugViewTest
{
// The following constant will appear in the debug window for DebugViewTest.
const string TabString = " ";
// The following DebuggerBrowsableAttribute prevents the property following it
// from appearing in the debug window for the class.
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";
static void Main()
{
MyHashtable myHashTable = new MyHashtable();
myHashTable.Add("one", 1);
myHashTable.Add("two", 2);
Console.WriteLine(myHashTable.ToString());
Console.WriteLine("In Main.");
}
}
[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;
}
}
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
private const string TestString = "This should not appear in the debug window.";
internal class HashtableDebugView
{
private Hashtable hashtable;
public const string TestString = "This should appear in the debug window.";
public HashtableDebugView(Hashtable hashtable)
{
this.hashtable = hashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePairs[] Keys
{
get
{
KeyValuePairs[] keys = new KeyValuePairs[hashtable.Count];
int i = 0;
foreach(object key in hashtable.Keys)
{
keys[i] = new KeyValuePairs(hashtable, key, hashtable[key]);
i++;
}
return keys;
}
}
}
}
using namespace System;
using namespace System::Collections;
using namespace System::Diagnostics;
using namespace System::Reflection;
ref class HashtableDebugView;
[DebuggerDisplay("{value}", Name = "{key}")]
ref class KeyValuePairs
{
private:
IDictionary^ dictionary;
Object^ key;
Object^ value;
public:
KeyValuePairs(IDictionary^ dictionary, Object^ key, Object^ value)
{
this->value = value;
this->key = key;
this->dictionary = dictionary;
}
};
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(HashtableDebugView::typeid)]
ref class MyHashtable : Hashtable
{
private:
static const String^ TestString = "This should not appear in the debug window.";
internal:
ref class HashtableDebugView
{
private:
Hashtable^ hashtable;
public:
static const String^ TestString = "This should appear in the debug window.";
HashtableDebugView(Hashtable^ hashtable)
{
this->hashtable = hashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState::RootHidden)]
property array<KeyValuePairs^>^ Keys
{
array<KeyValuePairs^>^ get()
{
array<KeyValuePairs^>^ keys = gcnew array<KeyValuePairs^>(hashtable->Count);
IEnumerator^ ie = hashtable->Keys->GetEnumerator();
int i = 0;
Object^ key;
while (ie->MoveNext())
{
key = ie->Current;
keys[i] = gcnew KeyValuePairs(hashtable, key, hashtable[key]);
i++;
}
return keys;
}
}
};
};
public ref class DebugViewTest
{
private:
// The following constant will appear in the debug window for DebugViewTest.
static const String^ TabString = " ";
public:
// The following DebuggerBrowsableAttribute prevents the property following it
// from appearing in the debug window for the class.
[DebuggerBrowsable(DebuggerBrowsableState::Never)]
static String^ y = "Test String";
static void Main()
{
MyHashtable^ myHashTable = gcnew MyHashtable();
myHashTable->Add("one", 1);
myHashTable->Add("two", 2);
Console::WriteLine(myHashTable->ToString());
Console::WriteLine("In Main.");
}
};
int main()
{
DebugViewTest::Main();
}