Mejorar la depuración con los atributos de visualización del depuradorEnhancing Debugging with the Debugger Display Attributes

Los atributos de visualización del depurador permiten al desarrollador del tipo, que especifica y mejor comprende el comportamiento del runtime de ese tipo, que especifique también el aspecto que tendrá ese tipo cuando se muestre en un depurador.Debugger display attributes allow the developer of the type, who specifies and best understands the runtime behavior of that type, to also specify what that type will look like when it is displayed in a debugger. Además, los atributos de visualización del depurador que proporcionan una propiedad Target pueden aplicarse en el nivel de ensamblado por usuarios sin conocimiento del código fuente.In addition, debugger display attributes that provide a Target property can be applied at the assembly level by users without knowledge of the source code. El atributo DebuggerDisplayAttribute controla la forma en que se muestra un tipo o un miembro en las ventanas de variables del depurador.The DebuggerDisplayAttribute attribute controls how a type or member is displayed in the debugger variable windows. El atributo DebuggerBrowsableAttribute determina si un campo o propiedad se muestra en las ventanas de variables del depurador y cómo se muestra.The DebuggerBrowsableAttribute attribute determines if and how a field or property is displayed in the debugger variable windows. El atributo DebuggerTypeProxyAttribute especifica un tipo sustitutivo, o un proxy, para un tipo y cambia la forma en que se muestra el tipo en las ventanas del depurador.The DebuggerTypeProxyAttribute attribute specifies a substitute type, or a proxy, for a type and changes the way the type is displayed in debugger windows. Cuando se ve una variable que tiene un proxy, o un tipo de sustitución, el proxy se corresponde con el tipo original en la ventana de presentación del depurador.When you view a variable that has a proxy, or substitute type, the proxy stands in for the original type in the debugger display window. En la ventana de las variables del depurador se muestran sólo los miembros públicos del tipo de servidor proxy.The debugger variable window displays only the public members of the proxy type. No se muestran los miembros privados.Private members are not displayed.

Usar el atributo DebuggerDisplayAttributeUsing the DebuggerDisplayAttribute

El constructor DebuggerDisplayAttribute tiene un argumento único: una cadena que se va a mostrar en la columna de valor de las instancias del tipo.The DebuggerDisplayAttribute constructor has a single argument: a string to be displayed in the value column for instances of the type. Esta cadena puede contener llaves ({ y }).This string can contain braces ({ and }). El texto encerrado entre llaves se evalúa como una expresión.The text within a pair of braces is evaluated as an expression. Por ejemplo, el código de C# siguiente hace que "Recuento = 4" se muestre cuando el signo más (+) está seleccionado para expandir la presentación del depurador para una instancia de MyHashtable.For example, the following C# code causes "Count = 4" to be displayed when the plus sign (+) is selected to expand the debugger display for an instance of MyHashtable.

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

Los atributos que se aplican en las propiedades a las que se hace referencia en la expresión no se procesan.Attributes applied to properties referenced in the expression are not processed. Para el compilador de C#, se permite una expresión general que solo tenga acceso implícito a esta referencia para la instancia actual del tipo de destino.For the C# compiler, a general expression is allowed that has only implicit access to this reference for the current instance of the target type. La expresión está limitada; no tiene acceso a los alias, variables locales ni punteros.The expression is limited; there is no access to aliases, locals, or pointers. En el código de C#, puede usar una expresión general entre las llaves que tenga acceso implícito al puntero this solo para la instancia actual del tipo de destino.In C# code, you can use a general expression between the braces that has implicit access to the this pointer for the current instance of the target type only.

Por ejemplo, si un objeto de C# tiene un ToString() invalidado, el depurador llamará a la invalidación y mostrará su resultado en lugar del {<typeName>}. estándar. Por lo tanto, si ha invalidado ToString(), no necesita usar DebuggerDisplayAttribute.For example, 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 DebuggerDisplayAttribute. Si utiliza ambos, el atributo DebuggerDisplayAttribute tiene prioridad sobre el reemplazo de ToString().If you use both, the DebuggerDisplayAttribute attribute takes precedence over the ToString() override.

Usar el atributo DebuggerBrowsableAttributeUsing the DebuggerBrowsableAttribute

Aplique DebuggerBrowsableAttribute en un campo o propiedad para especificar cómo va a mostrarse el campo o la propiedad en la ventana del depurador.Apply the DebuggerBrowsableAttribute to a field or property to specify how the field or property is to be displayed in the debugger window. El constructor de este atributo toma uno de los valores de enumeración DebuggerBrowsableState, que especifica uno de los estados siguientes:The constructor for this attribute takes one of the DebuggerBrowsableState enumeration values, which specifies one of the following states:

  • Never indica que el miembro no se muestra en la ventana de datos.Never indicates that the member is not displayed in the data window. Por ejemplo, con este valor para DebuggerBrowsableAttribute en un campo se quita el campo de la jerarquía; el campo no se muestra cuando expande el tipo envolvente haciendo clic en el signo más (+) para la instancia del tipo.For example, using this value for the DebuggerBrowsableAttribute on a field removes the field from the hierarchy; the field is not displayed when you expand the enclosing type by clicking the plus sign (+) for the type instance.

  • Collapsed indica que el miembro se muestra pero no se expande de manera predeterminada.Collapsed indicates that the member is displayed but not expanded by default. Este es el comportamiento predeterminado.This is the default behavior.

  • RootHidden indica que el propio miembro no se muestra, pero sus objetos constituyentes se muestran si es una matriz o una colección.RootHidden indicates that the member itself is not shown, but its constituent objects are displayed if it is an array or collection.

Nota

DebuggerBrowsableAttribute no es compatible con Visual Basic en la versión 2.0 de .NET Framework.The DebuggerBrowsableAttribute is not supported by Visual Basic in the .NET Framework version 2.0.

En el siguiente ejemplo de código se muestra el uso de DebuggerBrowsableAttribute para evitar que la propiedad que lo sigue aparezca en la ventana del depurador para la clase.The following code example shows the use of the DebuggerBrowsableAttribute to prevent the property following it from appearing in the debug window for the class.

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

Usar DebuggerTypeProxyUsing the DebuggerTypeProxy

Use el atributo DebuggerTypeProxyAttribute cuando necesite realizar cambios significativos y fundamentales en la vista de depuración de un tipo, sin cambiar el propio tipo.Use the DebuggerTypeProxyAttribute attribute when you need to significantly and fundamentally change the debugging view of a type, but not change the type itself. El atributo DebuggerTypeProxyAttribute se usa para especificar un servidor proxy de presentación de un tipo y permitir a un desarrollador que ajuste la vista para el tipo.The DebuggerTypeProxyAttribute attribute is used to specify a display proxy for a type, allowing a developer to tailor the view for the type. Este atributo, como DebuggerDisplayAttribute, también se puede usar en el nivel de ensamblado, en cuyo caso la propiedad Target especifica el tipo para el que se usará el servidor proxy.This attribute, like the DebuggerDisplayAttribute, can be used at the assembly level, in which case the Target property specifies the type for which the proxy will be used. El uso recomendado es que este atributo especifique un tipo anidado privado que aparece dentro del tipo al que se aplica el atributo.The recommended usage is that this attribute specifies a private nested type that occurs within the type to which the attribute is applied. Un evaluador de expresiones que admite los visores de tipo comprueba la existencia de este atributo cuando se muestra un tipo.An expression evaluator that supports type viewers checks for this attribute when a type is displayed. Si se encuentra el atributo, el evaluador de expresiones sustituye el tipo de servidor proxy de presentación por el tipo al que se aplica el atributo.If the attribute is found, the expression evaluator substitutes the display proxy type for the type the attribute is applied to.

Cuando está presente DebuggerTypeProxyAttribute, en la ventana de las variables del depurador se muestran solo los miembros públicos del tipo de servidor proxy.When the DebuggerTypeProxyAttribute is present, the debugger variable window displays only the public members of the proxy type. No se muestran los miembros privados.Private members are not displayed. El comportamiento de la ventana de datos no lo modifican las vistas mejoradas por atributos.The behavior of the data window is not changed by attribute-enhanced views.

Para evitar disminuciones innecesarias del rendimiento, los atributos del servidor proxy de presentación no se procesan hasta que el objeto esté expandido, ya sea a través del usuario que hace clic en el signo más (+) situado junto al tipo en una ventana de datos o a través de la aplicación del atributo DebuggerBrowsableAttribute.To avoid unnecessary performance penalties, attributes of the display proxy are not processed until the object is expanded, either through the user clicking the plus sign (+) next to the type in a data window, or through the application of the DebuggerBrowsableAttribute attribute. Por consiguiente, se recomienda no aplicar ningún atributo al tipo de presentación.Therefore, it is recommended that no attributes be applied to the display type. Los atributos pueden y deben aplicarse en el cuerpo del tipo de presentación.Attributes can and should be applied within the body of the display type.

En el ejemplo de código siguiente se muestra el uso del atributo DebuggerTypeProxyAttribute para especificar un tipo que se va a usar como servidor proxy de presentación del depurador.The following code example shows the use of the DebuggerTypeProxyAttribute to specify a type to be used as a debugger display proxy.

[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;
        }
    }
}

EjemploExample

DescripciónDescription

El siguiente ejemplo de código se puede ver en Visual Studio para ver los resultados de aplicar los atributos DebuggerDisplayAttribute, DebuggerBrowsableAttributey DebuggerTypeProxyAttribute.The following code example can be viewed in Visual Studio to see the results of applying the DebuggerDisplayAttribute, DebuggerBrowsableAttribute, and DebuggerTypeProxyAttribute attributes.

CódigoCode


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();
}
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;
            }
        }
    }
}
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
End Class
<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
End Class
<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

        <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
End Class

Consulte tambiénSee also