Asserzioni nel codice gestito
Le informazioni contenute in questo argomento sono valide per:
Edizione |
Visual Basic |
C# |
C++ |
Web Developer |
---|---|---|---|---|
Express |
||||
Pro, Premium e Ultimate |
Un'asserzione o un'istruzione Assert verifica una condizione specificata come argomento dell'istruzione Assert. Se la condizione restituisce true, non viene eseguita alcuna operazione. Se invece restituisce false, l'asserzione non riesce. In tal caso, se l'esecuzione avviene all'interno di una build di debug, nel programma verrà attivata la modalità di interruzione.
In Visual Basic e Visual C#, è possibile utilizzare il metodo Assert da Debug o Traceche si trovano nello spazio dei nomi System.Diagnostics. I metodi della classe Debug non sono inclusi in una versione di rilascio del programma, pertanto non aumentano la dimensione o non riducono la velocità del codice del rilascio.
In C++ non sono supportati i metodi della classe Debug. È possibile ottenere lo stesso effetto utilizzando la classe Trace con la compilazione condizionale, ad esempio #ifdef DEBUG... #endif.
Metodo Debug.Assert
Utilizzare il metodo Debug.Assert per verificare le condizioni che devono restituire true se il codice è corretto. Si supponga, ad esempio, di aver scritto una funzione di divisione fra interi. In base alle regole matematiche, il divisore non può mai essere pari a zero. Per verificare ciò, utilizzare un'asserzione:
[Visual Basic]
Function IntegerDivide(ByVal dividend As Integer, ByVal divisor As Integer) As Integer
Debug.Assert(divisor <> 0)
Return CInt(dividend / divisor)
End Function
[C#]
int IntegerDivide ( int dividend , int divisor )
{ Debug.Assert ( divisor != 0 );
return ( dividend / divisor ); }
Quando questo codice viene eseguito nel debugger, l'istruzione di asserzione verrà valutata ma nella versione di rilascio non verrà eseguito il confronto e pertanto non sarà generato alcun overhead aggiuntivo.
Di seguito è riportato un altro esempio. Si supponga che esista una classe che implementa un conto corrente come segue:
[Visual Basic]
Dim amount, balance As Double
balance = savingsAccount.balance
Debug.Assert(amount <= balance)
SavingsAccount.Withdraw(amount)
[C#]
float balance = savingsAccount.Balance;
Debug.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );
Prima di prelevare del denaro dal conto, si desidera verificare che il saldo sia sufficiente a coprire la somma di denaro che si intende ritirare. Per controllare il saldo, è possibile scrivere un'asserzione:
[Visual Basic]
Dim amount, balance As Double
balance = savingsAccount.balance
Trace.Assert(amount <= balance)
SavingsAccount.Withdraw(amount)
[C#]
float balance = savingsAccount.Balance;
Trace.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );
Le chiamate al metodo Debug.Assert scompaiono quando si crea una versione di rilascio del codice. Ciò significa che in tale versione la chiamata che controlla il saldo scomparirà. Per risolvere questo problema, sostituire Debug.Assert con Trace.Assert, che non scompare nella versione di rilascio.
A differenza dalle chiamate a Debug.Assert, le chiamate a Trace.Assert comportano un overhead nella versione di rilascio.
Effetti secondari di Debug.Assert
Quando si utilizza Debug.Assert, assicurarsi che il codice contenuto in Assert non modifichi i risultati del programma se Assert viene rimosso. In caso contrario, si potrebbe introdurre accidentalmente un bug che si manifesta solo nella versione di rilascio del programma. Prestare particolare attenzione alle asserzioni contenenti chiamate di funzione o di procedura, come quella del seguente esempio:
[Visual Basic]
' unsafe code
Debug.Assert (meas(i) <> 0 )
[C#]
// unsafe code
Debug.Assert (meas(i) != 0 );
Questo utilizzo di Debug.Assert può sembrare sicuro a una prima analisi. Si supponga, tuttavia, che la funzione meas aggiorni un contatore ogni volta che viene chiamata. Quando si compila la versione di rilascio, tale chiamata a meas viene eliminata e pertanto il contatore non viene aggiornato. Questo è un esempio di funzione con un effetto collaterale. L'eliminazione di una chiamata a una funzione che produce degli effetti collaterali, potrebbe comportare la generazione di un bug che si manifesta solo nella versione di rilascio. Per evitare tali problemi, non inserire chiamate di funzione in un'istruzione Debug.Assert, ma utilizzare una variabile temporanea.
[Visual Basic]
temp = meas( i )
Debug.Assert (temp <> 0)
[C#]
temp = meas( i );
Debug.Assert ( temp != 0 );
È possibile che si desideri evitare l'inserimento di chiamate di funzione in un'istruzione Assert anche quando si utilizza Trace.Assert. Questi tipi di chiamate non dovrebbero presentare rischi in quanto le istruzioni Trace.Assert non vengono eliminate nella build di rilascio. Se tuttavia si cerca di evitare sempre tali costrutti, è meno probabile che si commetta un errore quando si utilizza Debug.Assert.
Requisiti per la traccia e il debug
Quando si crea un progetto mediante le procedure guidate di Visual Studio, per impostazione predefinita il simbolo TRACE viene definito in entrambe le configurazioni di rilascio e di debug. Il simbolo DEBUG viene definito per impostazione predefinita solo nella build di debug.
In caso contrario, affinché i metodi Trace funzionino, è necessario che all'inizio del file di origine del programma sia presente una delle seguenti definizioni:
#Const TRACE = True in Visual Basic
#define TRACE in Visual C# e C++
In alternativa è necessario che il programma venga compilato con l'opzione TRACE:
/d:TRACE=True in Visual Basic
/d:TRACE in Visual C# e C++
Per utilizzare i metodi Debug in una build di rilascio C# o Visual Basic, è necessario definire il simbolo DEBUG nella configurazione di rilascio.
In C++ non sono supportati i metodi della classe Debug. È possibile ottenere lo stesso effetto utilizzando la classe Trace con la compilazione condizionale, ad esempio #ifdef DEBUG... #endif. È possibile definire questi simboli nella finestra di dialogo Pagine delle proprietà di <progetto>. Per ulteriori informazioni, vedere Impostazioni di progetto per una configurazione di debug Visual Basic o Impostazioni di progetto per una configurazione di debug C++.
Argomenti del metodo Assert
Trace.Assert e Debug.Assert accettano un massimo di tre argomenti. Il primo argomento è obbligatorio ed è costituito dalla condizione da controllare. Se si effettua una chiamata a Trace.Assert(Boolean) o Debug.Assert(Boolean) con un solo argomento, il metodo Assert controllerà la condizione e, se il risultato è false, invierà il contenuto dello stack di chiamate nella finestra di output. Nell'esempio riportato di seguito sono illustrati i metodi Trace.Assert(Boolean) e Debug.Assert(Boolean):
[Visual Basic]
Debug.Assert(stacksize > 0)
Trace.Assert(stacksize > 0)
[C#]
Debug.Assert ( stacksize > 0 );
Trace.Assert ( stacksize > 0 );
Il secondo e il terzo argomento, se disponibili, devono essere rappresentati da stringhe. Se si chiama il metodo Trace.Assert o Debug.Assert con due o tre argomenti, il primo argomento è una condizione. Il metodo verifica la condizione e, in presenza di un risultato false, genera la seconda e la terza stringa. Nell'esempio riportato di seguito viene illustrato l'utilizzo di Debug.Assert(Boolean, String) e Trace.Assert(Boolean, String) con due argomenti.
[Visual Basic]
Debug.Assert(stacksize > 0, "Out of stack space")
Trace.Assert(stacksize > 0, "Out of stack space")
[C#]
Debug.Assert ( stacksize > 0, "Out of stack space" );
Trace.Assert ( stacksize > 0, "Out of stack space" );
Nell'esempio riportato di seguito sono illustrati i metodi Assert e Assert:
[Visual Basic]
Debug.Assert(stacksize > 0, "Out of stack space. Bytes left:" , Format(size, "G"))
Trace.Assert(stacksize > 0, "Out of stack space. Bytes left:" , Format(size, "G"))
Trace.Assert(stacksize > 0, "Out of stack space. Bytes left:", "inctemp failed on third call" )
[C#]
Debug.Assert ( stacksize > 100, "Out of stack space" , "Failed in inctemp" );
Trace.Assert ( stacksize > 0, "Out of stack space", "Failed in inctemp" );
Personalizzazione del comportamento del metodo Assert
Se l'applicazione viene eseguita in modalità interfaccia utente, il metodo Assert visualizzerà la finestra di dialogo Asserzione non riuscita quando la condizione non restituisce true. Le azioni eseguite quando si verifica un errore di asserzione sono controllate dalla proprietà Listeners o Listeners.
È possibile personalizzare il comportamento di output aggiungendo un oggetto TraceListener all'insieme Listeners, rimuovendo un oggetto TraceListener dall'insieme Listeners oppure eseguendo l'override del metodo TraceListener.Fail di un oggetto TraceListener esistente in modo da ottenere un comportamento diverso.
È ad esempio possibile eseguire l'override del metodo TraceListener.Fail per scrivere in un log eventi anziché visualizzare la finestra di dialogo Asserzione non riuscita.
Per personalizzare l'output in questo modo, il programma deve contenere un listener ed è necessario ereditare da TraceListener, nonché eseguire l'override del relativo metodo TraceListener.Fail.
Per ulteriori informazioni, vedere Listener di traccia.
Impostazione di asserzioni in file di configurazione
Le asserzioni possono essere impostate sia nel file di configurazione del programma sia nel codice. Per ulteriori informazioni, vedere Trace.Assert o Debug.Assert.
Vedere anche
Attività
Procedura: compilare in modo condizionale con traccia e debug
Riferimenti
Concetti
Altre risorse
Traccia e strumentazione di applicazioni
Preparazione al debug: tipi di progetto C#, F# e Visual Basic