2009-06-05

DebuggerHiddenAttribute, DebuggerNonUserCodeAttribute, DebuggerStepThrough

Wszystkie trzy atrybuty najlepiej omówić razem, bo różnice pomiędzy nimi są subtelne. Atrybuty te posiadają konstruktory bezargumentowe. Atrybuty te nie podlegają dziedziczeniu. Najpierw powiedzmy sobie o opcji Just My Code. Opcja ta wpływa na działania wspomnianych trzech atrybutów. Ustawiamy ją w opcjach Visuala (Tools|Options): Wszystkie trzy atrybuty modyfikują zachowania debugera w następujących kwestiach:
  • czy debuger zatrzymuje się na breakpoincie w bloku kodu oznaczonym jednym z podanych atrybutów
  • czy debuger wykonuje Step Into w blok kodu oznaczony jednym z tych atrybutów
  • jak w podglądzie Call Stack pokazywane są wywołania metod oznaczonych tym atrybutem
Poniższa tabelka prezentuje różnice pomiędzy tymi trzema atrybutami:
AtrybutDebuggerHiddenDebuggerNonUserCodeDebuggerStepThrough
Just My CodeOnOffOnOffOnOff
BreakpointIgnorowanyIgnorowanyIgnorowanyDziałaIgnorowanyDziała
Step IntoOmijaOmijaOmijaDziałaOmijaOmija
Call StackBrak wpisuBrak wpisuExternal CodeJest wpisExternal CodeJest wpis
ZastosowanieProperty
Constructor
Method
Class
Struct
Property
Constructor
Method
Class
Struct
Property
Constructor
Method
Jeśli atrybutem objęta jest cała klasa lub struktura to atrybut ten stosuje się do wszystkich elementów klasy lub struktury. Choć atrybuty te można stosować do property to nie odniesie to żadnego skutku:
[System.Diagnostics.DebuggerNonUserCode()]
public int Z
{
    get
    {
        return 6;
    }
}
Zamiast tego atrybut należy stosować osobno dla gettera i settera. Atrybuty, które można stosować dla konstruktorów, można także stosować dla konstruktorów statycznych. Jeśli dokonujemy Step Into w kod oznaczony jednym z podanych atrybutów (i Just My Code jest tak ustawione, że z zgodnie z tabelką ten blok kodu zostanie przeskoczony), a z bloku tego wywoływane są inne bloki kodu nie oznaczone żadnym z powyższych 3 atrybutów, to właśnie na tamtym bloku zatrzyma się debuger (niezależnie od kombinacji Just My Code i atrybutów). To jak przeskoczona metoda zostanie pokazana w Call Stack podano w tabelce. Weźmy taki przykład, dla włączone Just My Code
[System.Diagnostics.DebuggerStepThrough()]
public int TestM()
{
    return TestMM();
}

public int TestMM()
{
    return 6;
}
Po wstawieniu breakpointa na zaznaczoną linię w Call Stack zobaczymy: To ukrycie w śladzie wywołania dotyczy tylko debugera, ślad stosu uzyskany z wyjątku lub za pomocą Console.WriteLine(Environment.StackTrace) będzie zawierać metodę TestM() Kiedy wyłączymy Just My Code, Call Stack będzie wyglądał tak: Tutaj, też widzimy zastosowanie tej opcji, polegające na ukrywaniu przed nami, wszelkich śladów wywołań, które nie dotyczą naszego kodu. Więcej informacji dostępnych jest tutaj. No i możliwa jest jeszcze taka kombinacja atrybutu i Just My Code, że ślad pomijanej metody nie będzie wogóle pokazywany: Atrybuty te powinniśmy stosować tylko dla dobrze przetestowanego kodu, by podczas debugowania nie szukać błędu i miejsca z błędem nie przeskakiwać. Można szybko docenić jego zalety implementując np. klasę liczby zespolonej, punktu, prostokąta, gdzie może być dużo małych upierdliwych metod, operatorów, konstruktorów wykonywanych setki razy.

Brak komentarzy:

Prześlij komentarz