Assertions in Managed Code
Note
This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here
An assertion, or Assert
statement, tests a condition, which you specify as an argument to the Assert
statement. If the condition evaluates to true, no action occurs. If the condition evaluates to false, the assertion fails. If you are running with a debug build, your program enters break mode.
In this topic
Asserts in the System.Diagnostics Namespace
Setting assertions in configuration files
Asserts in the System.Diagnostics Namespace
In Visual Basic and Visual C#, you can use the Assert
method from either Debug or Trace, which are in the System.Diagnostics namespace. Debug class methods are not included in a Release version of your program, so they do not increase the size or reduce the speed of your release code.
C++ does not support the Debug class methods. You can achieve the same effect by using the Trace class with conditional compilation, such as #ifdef DEBUG
... #endif
.
The Debug.Assert method
Use the System.Diagnostics.Debug.Assert method freely to test conditions that should hold true if your code is correct. For example, suppose you have written an integer divide function. By the rules of mathematics, the divisor can never be zero. You might test this using an assertion:
Function IntegerDivide(ByVal dividend As Integer, ByVal divisor As Integer) As Integer
Debug.Assert(divisor <> 0)
Return CInt(dividend / divisor)
End Function
int IntegerDivide ( int dividend , int divisor )
{ Debug.Assert ( divisor != 0 );
return ( dividend / divisor ); }
When you run this code under the debugger, the assertion statement is evaluated, but in the Release version, the comparison is not made, so there is no additional overhead.
Here is another example. You have a class that implements a checking account, as follows:
Dim amount, balance As Double
balance = savingsAccount.balance
Debug.Assert(amount <= balance)
SavingsAccount.Withdraw(amount)
float balance = savingsAccount.Balance;
Debug.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );
Before you withdraw money from the account, you want to make sure that the account balance is sufficient to cover the amount you are preparing to withdraw. You might write an assertion to check the balance:
Dim amount, balance As Double
balance = savingsAccount.balance
Trace.Assert(amount <= balance)
SavingsAccount.Withdraw(amount)
float balance = savingsAccount.Balance;
Trace.Assert ( amount <= balance );
savingsAccount.Withdraw ( amount );
Note that calls to the System.Diagnostics.Debug.Assert method disappear when you create a Release version of your code. That means that the call that checks the balance disappears in the Release version. To solve this problem, you should replace System.Diagnostics.Debug.Assert with System.Diagnostics.Trace.Assert, which does not disappear in the Release version:
Calls to System.Diagnostics.Trace.Assert add overhead to your Release version, unlike calls to System.Diagnostics.Debug.Assert.
Side effects of Debug.Assert
When you use System.Diagnostics.Debug.Assert, make sure that any code inside Assert
does not change the results of the program if Assert
is removed. Otherwise, you might accidentally introduce a bug that only shows up in the Release version of your program. Be especially careful about asserts that contain function or procedure calls, such as the following example:
' unsafe code
Debug.Assert (meas(i) <> 0 )
// unsafe code
Debug.Assert (meas(i) != 0 );
This use of System.Diagnostics.Debug.Assert might appear safe at first glance, but suppose the function meas updates a counter each time it is called. When you build the Release version, this call to meas is eliminated, so the counter does not get updated. This is an example of a function with a side effect. Eliminating a call to a function that has side effects could result in a bug that only appears in the Release version. To avoid such problems, do not place function calls in a System.Diagnostics.Debug.Assert statement. Use a temporary variable instead:
temp = meas( i )
Debug.Assert (temp <> 0)
temp = meas( i );
Debug.Assert ( temp != 0 );
Even when you use System.Diagnostics.Trace.Assert, you might still want to avoid placing function calls inside an Assert
statement. Such calls should be safe, because System.Diagnostics.Trace.Assert statements are not eliminated in a Release build. However, if you avoid such constructs as a matter of habit, you are less likely to make a mistake when you use System.Diagnostics.Debug.Assert.
Trace and Debug Requirements
If you create your project using the Visual Studio wizards, the TRACE symbol is defined by default in both Release and Debug configurations. The DEBUG symbol is defined by default only in the Debug build.
Otherwise, for Trace methods to work, your program must have one of the following at the top of the source file:
#Const TRACE = True
in Visual Basic#define TRACE
in Visual C# and C++Or your program must be built with the TRACE option:
/d:TRACE=True
in Visual Basic/d:TRACE
in Visual C# and C++If you need to use the Debug methods in a C# or Visual Basic Release build, you must define the DEBUG symbol in your Release configuration.
C++ does not support the Debug class methods. You can achieve the same effect by using the Trace class with conditional compilation, such as
#ifdef DEBUG
...#endif
. You can define these symbols in the <Project> Property Pages dialog box. For more information, see Changing Project Settings for a Visual Basic Debug Configuration or Changing Project Settings for a C or C++ Debug Configuration.
Assert arguments
System.Diagnostics.Trace.Assert and System.Diagnostics.Debug.Assert take up to three arguments. The first argument, which is mandatory, is the condition you want to check. If you call System.Diagnostics.Trace.Assert(Boolean) or System.Diagnostics.Debug.Assert(Boolean) with only one argument, the Assert
method checks the condition and, if the result is false, outputs the contents of the call stack to the Output window. The following example shows System.Diagnostics.Trace.Assert(Boolean) and System.Diagnostics.Debug.Assert(Boolean):
Debug.Assert(stacksize > 0)
Trace.Assert(stacksize > 0)
Debug.Assert ( stacksize > 0 );
Trace.Assert ( stacksize > 0 );
The second and third arguments, if present, must be strings. If you call System.Diagnostics.Trace.Assert or System.Diagnostics.Debug.Assert with two or three arguments, the first argument is a condition. The method checks the condition and, if the result is false, outputs the second string and third strings. The following example shows System.Diagnostics.Debug.Assert(Boolean, String) and System.Diagnostics.Trace.Assert(Boolean, String) used with two arguments:
Debug.Assert(stacksize > 0, "Out of stack space")
Trace.Assert(stacksize > 0, "Out of stack space")
Debug.Assert ( stacksize > 0, "Out of stack space" );
Trace.Assert ( stacksize > 0, "Out of stack space" );
The following example shows Assert and Assert:
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" )
Debug.Assert ( stacksize > 100, "Out of stack space" , "Failed in inctemp" );
Trace.Assert ( stacksize > 0, "Out of stack space", "Failed in inctemp" );
Customizing Assert behavior
If you run your application in user-interface mode, the Assert
method displays the Assertion Failed dialog box when the condition fails. The actions that occur when an assertion fails are controlled by the Listeners or Listeners property.
You can customize the output behavior by adding a TraceListener object to the Listeners
collection, by removing a TraceListener from the Listeners
collection, or by overriding the System.Diagnostics.TraceListener.Fail method of an existing TraceListener
to make it behave differently.
For example, you could override the System.Diagnostics.TraceListener.Fail method to write to an event log instead of displaying the Assertion Failed dialog box.
To customize the output in this way, your program must contain a listener, and you must inherit from TraceListener and override its System.Diagnostics.TraceListener.Fail method.
For more Information, see Trace Listeners.
Setting assertions in configuration files
You can set assertions in your program configuration file as well as in your code. For more information, see System.Diagnostics.Trace.Assert or System.Diagnostics.Debug.Assert.
See Also
System.Diagnostics.Debug.Assert
System.Diagnostics.Trace.Assert
Debugger Security
Tracing and Instrumenting Applications
How to: Compile Conditionally with Trace and Debug
C#, F#, and Visual Basic Project Types
Debugging Managed Code