Controllare il debug del codice grazie al namespace System.Diagnostics
Scritto da
Massimo Bonanni
il
mercoledì 26 gennaio 2011
Linguaggio:
•
Framework:
•
Livello: 100
In questo breve articolo vorrei mostrarvi come sia possibile
controllare il flusso di debug dei nostri applicativi utilizzando
alcune classi presenti nel namespace System.Diagnostics.
ConditionalAttribute
L'attributo ConditionaAttribute ci consente di includere (o
escludere) metodi dal flusso di esecuzione in base alla presenza o
meno di una costante di compilazione.
Ad esempio, supponiamo di avere la seguente applicazione
console:
Module Module1
Sub Main()
Console.WriteLine("Console start")
WriteLog()
Console.WriteLine("Console end")
End Sub
<Diagnostics.Conditional("LOG")>
Private Sub WriteLog()
Console.WriteLine("WriteLog")
End Sub
End Module
Se non definiamo la costante di compilazione LOG, il codice che
viene compilato è il seguente:

Come si può osservare, il corpo del metodo decorato con
l'attributo ConditionalAttribute è stato compilato ma non è stata
inserita la chiamata allo stesso che si sarebbe dovuta trovare tra
le due istruzioni Console.WriteLine del Main. Questo significa che,
quando eseguiamo, ad esempio, il debug della nostra applicazione,
vedremo il punto di esecuzione saltare la chiamata al metodo
WriteLog().
Definiamo, ora, la costante di compilazione LOG e per fare questo
apriamo la finestra delle proprietà dell'applicazione
console:

Se compiliamo dopo aver salvato
i cambiamenti alle proprietà otteniamo:

Il metodo, questa volta, viene
effettivamente richiamato.
La costante di compilazione è definibile anche, all'interno del
modulo, con la direttiva #Const nel seguente modo:
L'utilizzo dell'attributo ConditionalAttribute è una valida
alternativa ai costrutti #If...#End If anche se non è applicabile a
quei metodi che ritornano dei valori (function). In questo caso,
per poter applicare l'attributo è necessario convertire la function
in una sub e restituire il valore come argomento byref.
DebuggerDisplayAttribute
La classe DebuggerDisplayAttribute ci permette di personalizzare il
modo in cui appare il tootltip di debug di un tipo. Supponiamo di
avere la classe Employee:
Public Class Employee
Public Property LastName As String
Public Property FirstName As String
End Class
E di voler eseguire il debug di una semplice applicazione
console:

Il tooltip che ci permette di vedere i valori assunti
dalla variabile employee ci dice che la variabile è di tipo
Employee e ci obbliga ad aprire l'albero delle proprietà per vedere
il contenuto della stessa.
Per fare in modo che nel tooltip appaia una stringa riempita con i
valori contenuti nelle proprietà della variabile (che ci
permetterebbe a colpo d'occhio di capire che oggetto abbiamo in
debug), possiamo implementare l'override del metodo ToString.
Questo fatto ci obbliga, però, ad utilizzare un metodo che è, di
solito, utilizzato per scopi applicativi (ad esempio per mostrare i
dati in una listbox) per scopi di debug. Inoltre, non è detto
che le informazioni che dobbiamo mostrare in debug siano le stesse
da mostrare con il ToString(). Per risolvere questo problema ci
viene in aiuto l'attributo DebuggerDisplayAttribute il cui scopo è
definire come deve essere visualizzato il nostro oggetto quando
viene aperto il tooltip di debug:
<Diagnostics.DebuggerDisplay("Employee = {LastName} {FirstName}")>
Public Class Employee
Public Property LastName As String
Public Property FirstName As String
End Class
In questo modo otteniamo:

L'attributo può essere applicato ad assembly, classi, strutture,
campi, proprietà o delegate.
DebuggerHiddenAttribute
La classe DebuggerHiddenAttribute permette di "nascondere" un
costruttore, un metodo o una proprietà. Decorando un membro con
questo attributo facciamo si che quando si esegue il debug non si
possa eseguire uno step-into all'interno del metodo o fermarsi in
un breakpoint interno al metodo stesso.
Un esempio di utilizzo dell'attributo è il seguente:
Public Class Class1
Public Function NotHiddenMethod() As Boolean
Return True
End Function
<Diagnostics.DebuggerHidden()> _
Public Function HiddenMethod() As Boolean
Return True
End Function
End Class
Di fatto, il metodo HiddenMethod non può essere debuggato né
utilizzando lo step-into né inserendo un breakpoint all'interno
(per la cronaca l'ambiente di sviluppo permette di inserire il
breakpoint ma questo non è attivo).
DebuggerStepThroughAttribute
DebuggerStepThroughAttribute funziona in maniera analoga al
precedente attributo ma si limita solo a non permettere
l'esecuzione dello Step-Into nel metodo e non a disabilitare i
breakpoint interni. In più rispetto al precedente attributo, questo
può essere applicato anche a livello di classe o struttura in modo
da inibire tutti i membri della classe o struttura stessa.
In realtà l'attributo funziona in due differenti modalità in base
all'opzione "Enable Just My Code" impostata nelle proprietà di
debug del progetto:

Se è abilitata l'opzione Just My Code, l'attributo si comporta
esattamente come l'attributo precedente non permettendo neanche i
breakpoint interni ai membri decorati.
Se non è abilitata l'opzione Just My Code, invece, il flusso di
esecuzione in debug si fermerà su eventuali breakpoint interni ai
membri pur non permettendo lo step-into.
DebuggerBrowsableAttribute
L'attributo DebuggerBrowsable può essere applicato ad una proprietà
o ad un campo e permette di nascondere la proprietà o il campo
nella finestra di debug.
Ad esempio, prendiamo la classe:
Public Class Class1
Public Property VisibleProperty As String
<Diagnostics.DebuggerBrowsable(DebuggerBrowsableState.Never)>
Public Property InvisibleProperty As String
End Class
La proprietà InvisibleProperty, pur essendo pubblica, non sarà
visualizzata nella finestra di debug:

Il namespace System.Diagnostics contiene, oltre agli
attributi che consentono di controllare il flusso del debug delle
nostre applicazioni, anche tutta una serie di classi per interagire
con l'eventlog, i processi, i performance counters, etc., etc.
Maggiori informazioni al seguente link.
Tags: Visual Studio 2010,VB.NET