Using the .NET Micro Framework 4.1
I'm adding the following string keys (and string values, not relevant here) to a hashtable:
"eth::address"
"eth::netmask"
"eth::gateway"
"eth::dns"
"eth::port"
"com::baudrate"
"com::parity"
"com::databits"
"com::stopbits"
"com::handshake"
"com::read-timeout"
"com::write-timeout"
"drv::led-firmware-file"
"scr::width"
"scr::height"
"scr::colors"
When adding these to the HashTable no errors are thrown.
However, when looking at the properties & content of the hashtable I can see the following:
16 buckets, but 6 of them have a null key and null value. It's always the same ones.
What could be causing this?
Update:
There's not much code to post:
var settings = new HashTable(16);
settings.Add("eth::address", "192.168.1.1");
//Keep adding the settings mentioned above
No exceptions are thrown, in the end there are 16 items in the hashtable, starting with 3 valid ones, then a few null ones, then a few valid ones, etc....
There's nothing else involved as this is a simply a test case
If I try to get one of the values that "got lost", an exception is thrown:
var x = settings["eth::port"];
Will result in:
A first chance exception of type 'System.Exception' occurred in mscorlib.dll
An unhandled exception of type 'System.Exception' occurred in mscorlib.dll
enter code here
To extend Volkan's answer - checking the internal implementation of Hashtable
one might find the following:
public Hashtable(int capacity) : this(capacity, (float) 1f)
{
}
public Hashtable(int capacity, float loadFactor)
{
// arguments checking - elided
this.loadFactor = 0.72f * loadFactor;
double num = ((float) capacity) / this.loadFactor;
if (num > 2147483647.0)
{
throw new ArgumentException(
Environment.GetResourceString("Arg_HTCapacityOverflow"));
}
int num2 = (num > 3.0) ? HashHelpers.GetPrime((int) num) : 3;
this.buckets = new bucket[num2];
this.loadsize = (int) (this.loadFactor * num2);
this.isWriterInProgress = false;
}
So what happens when you initialize it with new Hashtable(16)
...? First, num
's value is computed to 16/0.72 = 22.(2)
. Then, HashHelpers.GetPrime(22)
kicks in, which looks like this:
internal static int GetPrime(int min)
{
// arguments checking - elided
for (int i = 0; i < primes.Length; i++)
{
int num2 = primes[i];
if (num2 >= min)
{
return num2;
}
}
// more code; irrelevant in this case - elided
}
Almost there. We only need to look up what primes
is.
static HashHelpers()
{
primes = new int[] { 3, 7, 11, 17, 23 /* more values */ };
}
With 22
as min
argument, we can easily see GetPrime
returns 23
. And this is the value used in Hashtable
constructor to create buckets array. You can perform same analysis for micro framework to see why it creates 16 buckets (which is weird TBH, considering it's good practice for buckets number to be prime value).