Что может привести к добавлению ключей к хэштебе быть нулевыми?

StackOverflow https://stackoverflow.com/questions/5805259

  •  24-10-2019
  •  | 
  •  

Вопрос

Использование .NET Micro Framework 4.1

Я добавляю следующие ключи строк (и строковые значения, не актуальные здесь) в хэштату:

"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"

При добавлении их в хэштибные ошибки не бросаются.

Однако, глядя на свойства и содержание хэштета, я вижу следующее:

16 ведра, но 6 из них имеют нулевое ключ и нулевое значение. Это всегда одно и то же.

Что может быть причиной этого?

Обновлять:

Не так много кода для публикации:

var settings = new HashTable(16);
settings.Add("eth::address", "192.168.1.1");
//Keep adding the settings mentioned above

Никаких исключений не брошено, в конце концов, в хэштате есть 16 элементов, начиная с 3 допустимых, затем несколько нулевых, затем несколько действительных и т. Д.

Нет ничего больше, так как это просто тестовый пример

The tool to inspect is #vs2010

Если я попытаюсь получить одну из значений, которые «потерялись», будет выброшено исключение:

var x = settings["eth::port"];

Приведет к:

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
Это было полезно?

Решение

Чтобы расширить ответ Волкана - проверка внутренней реализации Hashtable можно найти следующее:

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;
}

Так что происходит, когда вы инициализируете его с помощью new Hashtable(16)...? Первый, numЗначение вычисляется 16/0.72 = 22.(2). Анкет Затем, HashHelpers.GetPrime(22) Впитывает, что выглядит так:

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
}

Почти готово. Нам нужно только посмотреть, что primes является.

static HashHelpers()
{
    primes = new int[] { 3, 7, 11, 17, 23 /* more values */ };
}

С 22 в качестве min аргумент, мы можем легко увидеть GetPrime возврат 23. Анкет И это значение, используемое в Hashtable Конструктор, чтобы создать массив ведра. Вы можете выполнить тот же анализ для Micro -Framework, чтобы понять, почему он создает 16 ведра (что странно TBH, учитывая, что это хорошая практика, чтобы номер ведра был основным значением).

Другие советы

У меня нет доступа к микроммеру, но для .NET 4.0 я проверил с помощью образца, который вы дали, и он выделяет 23 ведра, 7 из них имеют нулевые значения. Каждое значение помещается в ведро с его хэш -кодом % 23. Например, eth :: gateway имеет хэш -код 1866092901, а его модуль 23 - 22, поэтому он помещен в 22 -е ведро. Почему вы беспокоитесь о стратегии распределения внутреннего ведра хэш -таблиц? Попробуйте код ниже в LinqPad, и вы можете быть уверены:

void Main()
{
    string[] vals = {"eth::address", "eth::netmask", .. all other strings... };
    var ht = new Hashtable(16);
    foreach (var v in vals) 
          ht[v] = v;
    var m = typeof(Hashtable).GetField("buckets", BindingFlags.NonPublic | BindingFlags.Instance);
    m.GetValue(ht).Dump();
    ht.Dump();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top