DekGenius.com
[ Team LiB ] Previous Section Next Section

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.

    [ Team LiB ] Previous Section Next Section