Как реализован словарь c # /. Net 3.5?

Я использую приложение, которое использует большое количество словарей (до 10 ^ 6 элементов), размер которых неизвестен заранее (хотя я могу догадаться в некоторых случаях). Мне интересно, как реализуется словарь, т. Е. Насколько плох этот эффект, если я не даю начальную оценку размера словаря. Внутренне ли он использует (саморазрастающийся) массив в том, как работает List? и в этом случае, если словари будут расти, может оставить много больших массивов без ссылки на LOH.

Используя Reflector , я нашел следующее: Словарь хранит данные в массиве struct. Он подсчитывает, сколько пустых мест осталось в этом массиве. Когда вы добавляете элемент и пустое место не остается, оно увеличивает размер внутреннего массива (см. Ниже) и копирует данные из старого массива в новый массив.

Поэтому я бы предложил вам использовать конструктор, в котором вы задаете начальный размер, если знаете, что будет много записей.

EDIT: Логика на самом деле довольно интересная: для поиска простых чисел существует внутренний class HashHelpers . Чтобы ускорить это, он также сохранил некоторые простые числа в статическом массиве от 3 до 7199369 (некоторые из них отсутствуют, по этой причине см. Ниже). Когда вы добавляете емкость, она находит следующий массив (то же значение или больше) из массива и использует его как начальную емкость. Если вы даете ему большее количество, чем в своем массиве, он начинает проверку вручную.

Поэтому, если в Словаре не передается ничто, стартовая емкость равна трем.

Как только пропускная способность превышена, она умножает текущую емкость на два, а затем находит следующее большее значение с использованием classа-помощника. Вот почему в массиве не требуется любое число, так как простые числа «слишком близко друг к другу» на самом деле не нужны.

Поэтому, если мы не получим начального значения, мы получим (я проверил внутренний массив):

  1. 3
  2. 7
  3. 17
  4. 37
  5. 71
  6. 163
  7. 353
  8. 761
  9. 1597
  10. 3371
  11. 7013
  12. 14591
  13. 30293
  14. 62851
  15. 130363
  16. 270371
  17. 560689
  18. 1162687
  19. 2411033
  20. 4999559

Как только мы пройдем этот размер, следующий шаг выпадет за пределами внутреннего массива, и он будет вручную искать большие простые числа. Это будет довольно медленно. Вы можете инициализировать с помощью 7199369 (наибольшее значение в массиве) или подумать, может ли иметь более 5 миллионов записей в словаре, что вы должны пересмотреть свой дизайн.

MSDN говорит: «Извлечение значения с помощью его ключа очень быстро, близко к O (1), потому что class Dictionary реализован как хеш-таблица». и далее «пропускная способность автоматически увеличивается, как требуется, перераспределяя внутренний массив».

Но вы получаете меньше перераспределений, если вы даете первоначальную оценку. Если у вас есть все элементы с самого начала, может оказаться полезным метод LINQ ToDictionary .

Обычно в Hashtables есть что-то, называемое коэффициентом нагрузки, что увеличит запас ведра, если этот порог будет достигнут. IIRC по умолчанию – это что-то вроде 0.72. Если у вас отличное хеширование, это можно увеличить до 1.0.

Также, когда хеш-таблице нужно больше ковшей, вся коллекция должна быть перефразирована.

Лучший способ для меня – использовать .NET Reflector.

http://www.red-gate.com/products/reflector/

Используйте дизассемблированный код, чтобы увидеть реализацию.

  • Проблема десериализации с помощью DataContractJsonSerializer
  • Многоязычный словарь в c #?
  • .NET - блокировка словаря против ConcurrentDictionary
  • Как получить доступ к глубоко вложенным словарям в Swift
  • Словарь VBA (Excel) на Mac?
  • Функции хранилища C # в словаре
  • Итерация через словарь в Swift
  • Дублировать ключи в словарях .NET?
  • Использование поля объекта в качестве общего ключа словаря
  • Рекурсивно обращаться к dict через атрибуты, а также доступ к индексу?
  • Сопоставление объекта со словарем и наоборот
  • Давайте будем гением компьютера.