Performing Assertions using the AssertionsDefinition class
In addition to using the MemAssertion
methods, e.g., NoInstances
and NoNewInstances
, it is also possible to perform assertions by using the MemAssertion.Assert method with the AssertionsDefinition class. This will give you access to additional assertions and more flexibility when defining the types included in the assertions. The AssertionsDefinition
class provides the possibility to define the expected memory usage in multiple steps, and it also contains additional assertions, such as MaxNewInstances
and MaxNewBytes
.
Note
Due to the added flexibility and functionality, using AssertionsDefinition
is recommended over using the MemAssertion
methods.
The assertions are defined by creating an instance of the AssertionsDefinition
class and then building the definition using the methods in the class.
The methods in the AssertionsDefinition class can be divided into three groups:
NoXXX
This group contains the methods NoInstances and NoNewInstances. These methods are used to define that no instances should exist of the specified types, unless the type has been specifically allowed using anAllowXXX
orMaxXXX
method.AllowXXX
This group contains the methods AllowInstances and AllowNewInstances. These methods are used to define that instances of the specified types are allowed to exist even if they have been restricted by a call to aNoXXX
method. Note that all types are allowed by default. If a type has not been restricted by aNoXXX
call, then allowing it usingAllowXXX
will have no effect.MaxXXX
This group contains the methods MaxInstances, MaxNewInstances, MaxBytes, and MaxNewBytes. These methods are used to define the maximum number of instances or bytes that are allowed to exist at the time of the assertion. They also override restrictions placed using aNoXXX
call.MaxAllocations/MaxAllocatedBytes
This group contains the methods MaxAllocations, MaxAllocatedBytes. These methods are used to define the maximum number of allocations or allocated bytes that are allowed to be performed until the time of the assertion.
Note that the order of the calls to the AssertionsDefinition methods is not relevant; an AllowXXX
or MaxXXX
call always takes precedence over a NoXXX
call. Consider the following two code snippets:
AssertionsDefinition ad = new AssertionsDefinition();
ad.NoNewInstances( typeof( Control ), true );
ad.AllowNewInstances( typeof( TextBox ) );
AssertionsDefinition ad = new AssertionsDefinition();
ad.AllowNewInstances( typeof( TextBox ) );
ad.NoNewInstances( typeof( Control ), true );
The above definitions are equal. An assertion using these definitions will fail if any new instance of a class derived from Control exists, except if the class is TextBox
.
When an assertions definition has been built, it can be asserted using the MemAssertion.Assert
method. The code example below shows how a memory assertion can be performed using an AssertionsDefinition.
using System.Drawing;
using SciTech.NetMemProfiler;
/// <summary>
/// This method opens up a form that allows the user
/// select a bitmap. The selected bitmap is loaded
/// and made available through the LoadedBitmap
/// property.
/// </summary>
Bitmap LoadBitmap()
{
using( LoadBitmapDialog dlg = new LoadBitmapDialog() )
{
dlg.ShowDialog();
return dlg.LoadedBitmap;
}
}
/// <summary>
/// Tests the memory usage of the LoadBitmap method.
/// </summary>
Bitmap TestLoadBitmap()
{
// Establish a base snapshot
MemProfiler.FastSnapshot();
Bitmap loadedBitmap = LoadBitmap();
// Assert that no new instances related to the
// System.Windows.Forms or System.Drawing
// namespaces have been created, except
// for a single Bitmap instance.
using( MemAssertion.BeginAssertions() )
{
AssertionsDefinition ad = new AssertionsDefinition();
// No new instances of any type in the
// System.Windows.Forms namespace should
// exist, including all types derived from
// a System.Windows.Forms type.
ad.NoNewInstances( “System.Windows.Forms.*”, true );
// No new instances of any type in the
// System.Drawing namespace should
// exist, including all types derived from
// a System.Drawing type.
ad.NoNewInstances( “System. Drawing.*”, true );
// Since a Bitmap is returned, we must allow 1
// new Bitmap to be created. The MaxNewInstances
// assertion will override the NoNewInstances
// assertion above.
ad.MaxNewInstances( typeof( Bitmap ), 1 );
// The AssertionsDefinition has been built,
// let’s perform the actual assertion.
MemAssertion.Assert( ad );
}
return loadedBitmap;
}
For more information about AssertionsDefinition and the MemAssertion.Assert method, see the .NET Memory Profiler API Reference documentation.