Recipe 9.11 Creating a Hashtable with Max and Min Size Boundaries
Problem
You need to use a
Hashtable in your project that allows you to set
the maximum and/or minimum number of elements that it can hold.
Solution
Use the MaxMinSizeHashtable class defined here.
This class allows a definition of a maximum and a minimum size beyond
which this MaxMinSizeHashtable cannot grow or
shrink:
using System;
using System.Collections;
[Serializable]
public class MaxMinSizeHashtable : Hashtable
{
public MaxMinSizeHashtable( ) : base(10)
{
}
public MaxMinSizeHashtable(int minSize, int maxSize)
: base(maxSize)
{
if (minSize >= 0 && maxSize > 0)
{
this.minSize = minSize;
this.maxSize = maxSize;
}
}
protected int minSize = 0;
protected int maxSize = 10; // Initial size for a regular Hashtable
protected bool readOnly = false;
public bool ReadOnly
{
get {return (readOnly);}
set {readOnly = value;}
}
public override bool IsReadOnly
{
get {return readOnly;}
}
public override object this[object key]
{
get
{
return (base[key]);
}
set
{
if (!readOnly)
{
if (key is long)
{
if (long.Parse(key.ToString( )) < maxSize &&
long.Parse(key.ToString( )) > minSize)
{
base[key] = value;
}
else
{
throw (new ArgumentOutOfRangeException("key", key,
"The key is outside the minimum/maximum" +
" boundaries."));
}
}
else
{
base[key] = value;
} }
else
{
throw (new ArgumentOutOfRangeException("value", value,
"This Hashtable is currently set to read-only."));
}
}
}
public override void Add(object key, object value)
{
if (!readOnly)
{
if (this.Count < maxSize)
{
base.Add(key, value);
}
else
{
throw (new ArgumentOutOfRangeException("value", value,
"No more values can be added to this Hashtable, " +
"until one is removed"));
}
}
else
{
throw (new ArgumentOutOfRangeException("value", value,
"This Hashtable is currently set to read-only."));
}
}
public override void Remove(object key)
{
if (!readOnly)
{
if (this.Count > minSize)
{
base.Remove(key);
}
else
{
throw (new InvalidOperationException(
"No more values can be removed from this Hashtable, " +
"until one is added"));
}
}
else
{
throw (new NotSupportedException(
"This Hashtable is currently set to read-only."));
}
}
public override void Clear( )
{
if (!readOnly)
{
if (minSize == 0)
{
base.Clear( );
}
else
{
throw (new InvalidOperationException(
"Clearing this Hashtable would go below the minimum " +
"size of " + minSize));
}
}
else
{
throw (new InvalidOperationException(
"This Hashtable is currently set to read-only."));
}
}
}
Discussion
The MaxMinSizeHashtable class inherits from
Hashtable and overrides the members that allow
Hashtable values to be added, removed, and
modified. The overloaded constructor for the
MaxMinSizeHashtable class is defined here:
public MaxMinSizeHashtable(int minSize, int maxSize)
Its parameters are:
minSize
The smallest number of elements this class can contain
maxSize
The largest number of elements this class can contain
A public Boolean property called ReadOnly has been
added to this class to allow or prevent the use of the
Add, Remove, and
Clear methods.
The overloaded Add method will add the object to
the MaxMinSizeHashtable only when it is not
read-only and the current size is less than the
maxSize field. If all tests pass, the value is
added to the MaxMinSizeHashtable.
The overloaded Remove method is overloaded to
validate that the size of the MaxMinSizeHashtable
does not fall below the number specific by the
minSize field. The Clear method
is also overridden to verify that the minSize
field is zero before this operation is allowed to proceed, since this
operation will leave zero elements in this
MaxMinSizeHashtable.
As a final point, the overloaded constructor accepts
minSize and
maxSize as signed integers. Obviously the
MaxMinSizeHashtable cannot have a negative size.
The reason for this is compliance with other .NET languages that may
use this class. The unsigned numeric types are not included in the
CLS; therefore, they are not CLS-compliant.
Consider what would happen if a Visual Basic .NET object-which
does not handle unsigned numeric types-tried to use this
object. If the MaxMinSizeHashtable constructor
accepted only uint types and a Visual Basic .NET
class attempted to instantiate an instance of the
MaxMinSizeHashtable:
' Visual Basic .NET code
Dim Table As New MaxMinSizeHashtable(2, 4)
the Visual Basic .NET compiler would complain that a value of type
Integer could not be converted to a
System.UInt32 type. Visual Basic .NET has no
ability to convert types to and from unsigned types. To make this
object and many others in this book compliant, we choose to use
signed rather than unsigned numeric types where possible.
See Also
See the "Hashtable Class" topic in
the MSDN documentation.
|