Dela via


Förbättra felsökning med visningsattribut för felsökningsprogrammet

Kommentar

Den här artikeln är specifik för .NET Framework. Det gäller inte för nyare implementeringar av .NET, inklusive .NET 6 och senare versioner.

Med visningsattribut för felsökningsprogram kan utvecklaren av typen, som anger och bäst förstår körningsbeteendet för den typen, även ange hur den typen ska se ut när den visas i ett felsökningsprogram. Dessutom kan visningsattribut för felsökningsprogram som tillhandahåller en Target egenskap tillämpas på sammansättningsnivå av användare utan att känna till källkoden. Attributet DebuggerDisplayAttribute styr hur en typ eller medlem visas i felsökarvariabelns fönster. Attributet DebuggerBrowsableAttribute avgör om och hur ett fält eller en egenskap visas i variabelfönstren för felsökningsprogrammet. Attributet DebuggerTypeProxyAttribute anger en ersättningstyp, eller en proxy, för en typ och ändrar hur typen visas i felsökningsfönster. När du visar en variabel som har en proxy eller ersättningstyp, står proxyn för den ursprungliga typen i visningsfönstret för felsökningsprogrammet. Variabelfönstret för felsökningsprogrammet visar endast de offentliga medlemmarna av proxytypen. Privata medlemmar visas inte.

Använda DebuggerDisplayAttribute

Konstruktorn DebuggerDisplayAttribute har ett enda argument: en sträng som ska visas i värdekolumnen för instanser av typen. Den här strängen kan innehålla klammerparenteser ({ och }). Texten inom ett par klammerparenteser utvärderas som ett uttryck. Följande C#-kod gör till exempel att "Count = 4" visas när plustecknet (+) har valts för att expandera felsökningsprogrammets visning för en instans av MyHashtable.

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

Attribut som tillämpas på egenskaper som refereras i uttrycket bearbetas inte. För C#-kompilatorn tillåts ett allmänt uttryck som endast har implicit åtkomst till den här referensen för den aktuella instansen av måltypen. Uttrycket är begränsat. Det finns ingen åtkomst till alias, lokala platser eller pekare. I C#-kod kan du använda ett allmänt uttryck mellan de klammerparenteser som har implicit åtkomst till pekaren this endast för den aktuella instansen av måltypen.

Om ett C#-objekt till exempel har ett åsidosättning ToString()anropar felsökaren åsidosättningen och visar resultatet i stället för standarden {<typeName>}. Så om du har åsidosatt ToString()behöver du inte använda DebuggerDisplayAttribute. Om du använder båda DebuggerDisplayAttribute har attributet företräde framför åsidosättningen ToString() .

Använda DebuggerBrowsableAttribute

Använd på DebuggerBrowsableAttribute ett fält eller en egenskap för att ange hur fältet eller egenskapen ska visas i felsökningsfönstret. Konstruktorn för det här attributet tar ett av DebuggerBrowsableState uppräkningsvärdena, som anger något av följande tillstånd:

  • Never anger att medlemmen inte visas i datafönstret. Om du till exempel använder det här värdet för DebuggerBrowsableAttribute fältet på ett fält tas fältet bort från hierarkin. Fältet visas inte när du expanderar omslutningstypen genom att klicka på plustecknet (+) för typinstansen.

  • Collapsed anger att medlemmen visas men inte expanderas som standard. Det här är standardbeteendet.

  • RootHidden anger att själva medlemmen inte visas, men dess konstituerande objekt visas om det är en matris eller samling.

Kommentar

DebuggerBrowsableAttribute Stöds inte av Visual Basic i .NET Framework version 2.0.

I följande kodexempel visas användningen av DebuggerBrowsableAttribute för att förhindra att egenskapen som följer den visas i felsökningsfönstret för klassen.

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

Använda DebuggerTypeProxy

DebuggerTypeProxyAttribute Använd attributet när du behöver avsevärt och i grunden ändra felsökningsvyn för en typ, men inte ändra själva typen. Attributet DebuggerTypeProxyAttribute används för att ange en visningsproxy för en typ, så att en utvecklare kan skräddarsy vyn för typen. Det här attributet, till exempel DebuggerDisplayAttribute, kan användas på sammansättningsnivå, i vilket fall Target egenskapen anger vilken typ proxyn ska användas för. Den rekommenderade användningen är att det här attributet anger en privat kapslad typ som inträffar inom den typ som attributet tillämpas på. En uttrycksutvärdering som stöder typvisning söker efter det här attributet när en typ visas. Om attributet hittas ersätter uttrycksutvärderaren visningsproxytypen för den typ som attributet tillämpas på.

När är DebuggerTypeProxyAttribute närvarande visar felsökningsvariabelfönstret endast de offentliga medlemmarna av proxytypen. Privata medlemmar visas inte. Datafönstrets beteende ändras inte av attributförstärkta vyer.

För att undvika onödiga prestandapåföljder bearbetas inte attribut för visningsproxyn förrän objektet har expanderats, antingen genom att användaren klickar på plustecknet (+) bredvid typen i ett datafönster eller genom attributets DebuggerBrowsableAttribute tillämpning. Därför rekommenderar vi att inga attribut tillämpas på visningstypen. Attribut kan och bör tillämpas i brödtexten i visningstypen.

I följande kodexempel visas användningen av DebuggerTypeProxyAttribute för att ange en typ som ska användas som en visningsproxy för felsökningsprogrammet.

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

Exempel

beskrivning

Följande kodexempel kan visas i Visual Studio för att se resultatet av att tillämpa attributen DebuggerDisplayAttribute, DebuggerBrowsableAttributeoch DebuggerTypeProxyAttribute .

Code


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 - 1) 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

Se även