使用调试器显示属性增强调试

更新:2007 年 11 月

调试器显示属性允许类型的开发人员(他们指定并且最理解该类型的运行时行为)同时指定该类型显示在调试器中时的外观。此外,用户无需知道源代码即可在程序集级别应用提供 Target 属性 (Property) 的调试器显示属性 (Attribute)。DebuggerDisplayAttribute 属性控制如何在调试器变量窗口中显示类型或成员。DebuggerBrowsableAttribute 属性 (Attribute) 确定是否以及如何在调试器变量窗口中显示某个字段或属性 (Property)。DebuggerTypeProxyAttribute 属性指定某个类型的替代类型或代理,并更改在调试器窗口中显示该类型的方式。在查看具有代理或替代类型的变量时,该代理在调试器显示窗口中代表原始类型。 调试器变量窗口仅显示代理类型的公共成员。 不显示私有成员。

使用 DebuggerDisplayAttribute

DebuggerDisplayAttribute 构造函数具有单个参数:要在类型实例的值列中显示的字符串。此字符串可以包含大括号({ 和 })。大括号对中的文本按表达式进行求值。例如,当选择加号 (+) 展开 MyHashtable 的实例的调试器显示时,下面的 C# 代码导致“Count = 4”被显示出来。

[DebuggerDisplay("Count = {count}")]
class MyHashtable
{
    public int count = 4;
}

应用于表达式中引用的属性 (Property) 的属性 (Attribute) 未被处理。对于 C# 编译器,允许使用常规表达式,这些表达式只能对目标类型的当前实例的 this 引用进行隐式访问。该表达式是受限制的,不存在对别名、局部变量或指针的访问。在 C# 代码中,可以在大括号之间使用常规表达式,它们只能对目标类型的当前实例的 this 指针进行隐式访问。

例如,如果 C# 对象重写了 ToString(),则调试器将调用该重写,并显示其结果而不是显示标准的 {<typeName>}.。因此,如果重写了 ToString(),则不需要使用 DebuggerDisplayAttribute。在同时使用这两者时,DebuggerDisplayAttribute 属性将优先于 ToString() 重写。

使用 DebuggerBrowsableAttribute

DebuggerBrowsableAttribute 应用于某个字段或属性,以指定如何在调试器窗口中显示该字段或属性。此属性的构造函数采用 DebuggerBrowsableState 枚举值之一,该值指定下列状态之一:

  • Never 指示不在数据窗口中显示该成员。 例如,将此值用于某个字段上的 DebuggerBrowsableAttribute 将从层次结构中移除该字段;通过单击类型实例的加号 (+) 展开封闭类型时,不会显示该字段。

  • Collapsed 指示显示该成员,但是默认不展开。 这是默认行为。

  • RootHidden 指示不显示该成员自身,但是如果它是数组或集合,则显示其构成对象。

ms228992.alert_note(zh-cn,VS.90).gif说明:

.NET Framework 2.0 版中的 Visual Basic 不支持 DebuggerBrowsableAttribute

下面的代码示例演示如何使用 DebuggerBrowsableAttribute 阻止它后面的属性出现在类的调试窗口中。

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";

使用 DebuggerTypeProxy

在需要显著或根本性地更改类型的调试视图但是不更改类型自身时,应使用 DebuggerTypeProxyAttribute 属性。DebuggerTypeProxyAttribute 属性用于指定类型的显示代理,允许开发人员定制类型的视图。 此属性 (Attribute) 与 DebuggerDisplayAttribute 类似,可以在程序集级别使用,在这种情况下,Target 属性 (Property) 指定将为其使用代理的类型。建议的用法是此属性指定一个私有嵌套类型,它出现在该属性所应用到的类型中。 支持类型查看器的表达式计算器在某个类型被显示时检查此属性。如果找到该属性,表达式计算器将使用显示代理类型替换该属性所应用到的类型。

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 中查看下面的代码示例以确定应用 DebuggerDisplayAttributeDebuggerBrowsableAttributeDebuggerTypeProxyAttribute 属性的结果。

代码

Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Reflection



Class DebugViewTest

    Shared Sub Main(ByVal args() As String) 
        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 Const TestString As String = "This should appear in the debug window."

        Public Sub New(ByVal hashtable As Hashtable)
            Me.hashtable = hashtable

        End Sub 'New
    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(string[] args)
    {
        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;
         }
      }
   }
}

请参见

参考

DebuggerDisplayAttribute

DebuggerBrowsableAttribute

DebuggerTypeProxyAttribute