Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc

Debugger i atrybuty, czyli jak usprawniać sobie codzienną pracę

Każdy programista pewną część swojego życia spędza z... debuggerem ;) Chyba zgodzicie się ze mną, że jest to bardzo przydatne narzędzie. Gdy pojawia się jakiś błąd i nie do końca wiemy co w trawie piszczy to odpalamy go i linia po lini weryfikujemy nasz program. Czasami jednak debugowanie może być uciążliwe... Pokażę kilka atrybutów, którymi możemy podpowiadać debuggerowi.

Zaglądanie do getterów, które podajemy jako parametry wywołania metody.

Najczęstszym problemem, który napotykam podczas debugowania to denerwujące wskakiwanie debuggera do getterów właściwości, które przekazuję w wywołaniu metody. Zwykle taki getter nie ma żadnej dodatkowej logiki tylko zwraca wartość prywatnego pola. Mając metodę z kilkoma tak podanymi parametrami łatwo się zgubić. Wiele razy w pośpiechu wciskałem F10, żeby wyskoczyć z tego gettera i okazywało się, że nacisnąłem o jeden raz za dużo i ominąłem wywołanie metody (sic!). Żeby było śmieszniej zwykle zdarza mi się to przy ostatnim parametrze metody! Na szczęście jest na to ratunek. W System.Diagnostics znajduje się atrybut DebuggerStepThroughAttribute, który zaaplikowany do metody lub właściwości karze debuggerowi ominąć oznaczony element i zatrzymać się po jego wykonaniu :) Zatem naszą znienawidzoną właściwość wystarczy udekorować:

private string _myProperty;
public string MyProperty
{
    [DebuggerStepThrough]
    get { return _myProperty; }
}


Tak oznaczonej właściwości już nie zobaczymy pod czas debugowania :D.

Przeglądanie zawartości złożonych obiektów

Czasami budujemy złożone klasy. Mogą to być na przykład takie zawierające wewnętrzne listy bądź też całkiem proste, z których budujemy większe struktury (np. węzły drzewa). Debugując taką klasę mamy utrudnione zadanie ponieważ musimy rozwijać różne elementy, żeby w końcu zobaczyć co zawiera ta wewnętrzna lista, albo zaglądać do elementów wgłąb tak jak to ma miejsce przy debugowaniu drzew. Przykładowe debugowanie drzewa binarnego wygląda tak:



Jak widać na załączonym obrazku wyciągnięcie wartości, które nas rzeczywiście interesują, czyli wartości w poszczególnych węzłach, jest trudne. Obraz jest zaciemniony przez inne pola. Istnieje jednak sposób, aby ułatwić sobie życie - atrybut DebuggerTypeProxyAttribute. Za jego pomocą możemy określić proxy, które będzie wyświetlanie podczas debugowania. Klasę proxy definiuje się bardzo łatwo. Może to być dowolna klasa, która posiada konstruktor przyjmujący parametr typu klasy, którą opatrzymy tym atrybutem. Podczas debugowania to klasa proxy będzie wyświetlana, czyli zobaczymy to, co w niej zdefiniujemy. W przykładzie z drzewem zdefiniowałem sobie taką klasę i dodałem do niej publiczne pole InOrder, które zwraca wartości drzewa właśnie w takim porządku:

[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public string[] InOrder
{
    get
    {
        List<String> result = new List<string>();
        GetInOrder(this._node, result, "");
        return result.ToArray();
    }
}


Należy tutaj zauważyć kolejny pomocny atrybut. DebuggerBrowsableAtribute służy do podpowiadania debuggerowi jak wyświetlać dane pole. Do dyspozycji mamy trzy wartości: Collapsed - element będzie zwinięty, Never - element nie będzie pokazywany oraz RootHidden - element nie będzie pokazywany, ale zamiast niego zostaną wstawione jego podelementy. W powyższym przykładzie ukryłem element InOrder, aby od razu wyświetlały się elementy listy, którą zwraca. W taki oto sposób debugowanie stało się o wiele prostsze:



Jak nie trudno zauważyć zawartość drzewa jest banalna do odczytania.

Wyświetlanie złożonych obiektów

Ostatnim atrybutem, o którym chciałem jeszcze wspomnieć jest DebuggerDisplayAttribute, który służy do definiowania napisu, który będzie wyświetlany dla złożonego elementu (klasy). Aplikując go podajemy również napis, który będzie wyświetlany. W tym napisie możemy odwoływać się do właściwości obiektu poprzez {Property}:

[DebuggerDisplay("Val: {Value}, Desc: {Description}")]
class SimpleClass
{
    private int _value;
    public int Value {...}
    private string _description;
    public string Description {...}
    public SimpleClass(int value, string description) {...}
}


Dzięki niemu nasza klasa będzie widoczna w debuggerze w następujący sposób:



Przedstawiłem tu techniki, z których korzystam na co dzień. Może i wam się przydadzą. :)
W załączniku zamieściłem przykładowy program dla ciekawskich.
Opublikowane 6 października 2007 00:10 przez nuwanda
Attachment(s): DebuggerProxyTest.zip

Powiadamianie o komentarzach

Jeżeli chciałbyś otrzymywać email gdy ta wypowiedź zostanie zaktualizowana, to zarejestruj się tutaj

Subskrybuj komentarze za pomocą RSS

Komentarze:

# re: Debugger i atrybuty, czyli jak usprawniać sobie codzienną pracę

8 października 2007 20:30 by arkadiusz.wasniewski

Warte poznania 10/10.

Arek

Co o tym myślisz?

(wymagane) 
wymagane 
(wymagane) 

  
Wprowadź kod: (wymagane)