Dictionary c что это

от admin

Dictionary c что это

Еще один распространенный тип коллекции представляют словари. Словарь хранит объекты, которые представляют пару ключ-значение. Класс словаря Dictionary<K, V> типизируется двумя типами: параметр K представляет тип ключей, а параметр V предоставляет тип значений.

Создания и инициализация словаря

Класс Dictionary предоставляет ряд конструкторов для создания словаря. Например, мы можем создать пустой словарь:

Здесь словарь people в качестве ключей принимает значения типа int, а в качестве значений — строки.

При определении словаря его сразу же можно инициализировать значениями:

При инициализации применяется инициализитор — в фигурных скобках после вызова конструктора объекту передаются начальные данные. В случае со словаем мы можем передать в инициализаторе набор элементов, где каждый элемент заключается в фигурные скобки, например:

Каждый элемент представляет два значения: первое значение представляет ключ, а второе значение — собственно значение элемента. Поскольку при объявлении словаря people для ключей указан тип int , а для значений — тип string , то в элементе словаря сначала указывается число int, а затем строка. То есть в случае выше элемент имеет ключ 5, а значение — «Tom». Затем по ключу элемента мы сможем получить его значение.

Также мы можем применять другой способ инициализации:

При таком способе инициализации в квадратных скобках указывается ключ и ему присваивается значение элемента. Но в целом этот способ инициализации будет равноценен предыдущему.

KeyValuePair

Стоит отметить, что каждый элемент в словаре представляет структуру KeyValuePair<TKey, TValue> , где параметр TKey представляет тип ключа, а параметр TValue — тип значений элементов. Эта структура предоставляет свойства Key и Value , с помощью которых можно получить соответственно ключ и значение элемента в словаре. И одна из версий конструктора Dictionary позволяет инициализировать словарь коллекцией объектов KeyValuePair:

Конструктор типа KeyValuePair принимает два параметра — ключ элемента и его значения. То есть в данном случае создается один такой элемент — mike с ключом 56 и значением «Mike». И этот элемент добавляется в список employees, которым затем инициализируется словарь.

Можно совместить оба способа инициализации:

В данном случае в словаре people будет четыре элемента.

Перебор словаря

Для перебора словаря можно применять цикл foreach :

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

Получение элементов

Для обращения к элементам из словаря применяется их ключ, который передается в квадратных скобках:

Таким образом мы можем получить и изменить элементы словаря

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

Методы и свойства Dictionary

Среди методов класса Dictionary можно выделить следующие:

void Add(K key, V value) : добавляет новый элемент в словарь

void Clear() : очищает словарь

bool ContainsKey(K key) : проверяет наличие элемента с определенным ключом и возвращает true при его наличии в словаре

bool ContainsValue(V value) : проверяет наличие элемента с определенным значением и возвращает true при его наличии в словаре

bool Remove(K key) : удаляет по ключу элемент из словаря

Другая версия этого метода позволяет получить удленный элемент в выходной параметр: bool Remove(K key, out V value)

bool TryGetValue(K key, out V value) : получает из словаря элемент по ключу key. При успешном получении передает значение элемента в выходной параметр value и возвращает true

bool TryAdd(K key, V value) : добавляет в словарь элемент с ключом key и значением value. При успешном добавлении возвращает true

Из свойств следует отметить свойство Count , которое возвращает количество элементов в словаре.

Dictionary в .NET

В этой статье рассматриваем какие типы Dictionary бывают в C# и смотрим под капот и более глубоко по работе с ними. Частично Dictionary и другие коллекции мы затрагивали в этой статье.

Оглавление:

Dictionary

Словарь (dictionary) — это обобщенная версия Hashtable содержащая в себе объект структуры KeyValuePair<TKey, TValue> . Главное свойство dictionary— быстрый поиск с помощью ключей. Можно также добавлять и удалять элементы, наподобие того как это делается в List<T> , но без расходов производительности, связанных с необходимостью смещения последующих элементов в памяти.

На диаграмме ниже вы можете увидеть упрощенную модель dictionary. Здесь ключами словаря служат ID, такие, как: 1,2,3. Ключ в последствии трансформируется в хэш. В хэше создается число для ассоциации индекса с Value. После этого индекс содержит ссылку на Value.

dictionary diagram

Требования к ключу Dictionary

Dictionary использует метод GetHashCode() класса Object для вычисления целого числа которое используется для поиска индекса для вставки нового значения.

Реализовывая свой кастомный GetHashCode() вы должны удовлетворить следующие требования:

Один и тот же объект должен всегда возвращать одинаковый хэш-код (Хэш-код не должен изменятся во время жизни объекта).

Разные объекты могут возвращать одно и то же значение хэш-кода.

Метод должен выполняться очень быстро.

Он не должен генерировать эксепшенов.

Он должен использовать как минимум одно поле экземпляра.

Значения хэш-кода должны распределяться равномерно по всему диапазону чисел, которые может хранить int.

Зачем равномерно распределять значения хэш-кода по диапазону целых чисел?

Если два ключа возвращают хэш-значения, дающие один и тот же индекс, Dictionary приходится искать ближайшее доступное свободное место для сохранения второго элемента, к тому же ему придется выполнять некоторый поиск, чтобы впоследствии извлечь требуемое значение. Это сильно влияет на производительность, Microsoft, разработала хороший алгоритм который вычисляет значение хэш-кода равномерно распределено между int.MinValue и int.MaxValue. Следовательно, это снижает угрозу с производительностью Dictionary, а значит всегда старайтесь использовать стандартный метод GetHashCode от Майкрософт. Более детально про Equals можно почитать в этой статье.

Поскольку разные объекты ключа могут возвращать один и тот же хэш-код, метод Equals() используется при сравнении ключей словаря. Словарь проверяет два ключа А и В на эквивалентность, вызывая A.Equals(В)

Insert

Если мы обратимся к исходному коду словаря, то у видим что словаря есть один очень важный field private int[] buckets; который используется в словаре для быстрой вставки и поиска значений в словаре.

dictionary source code

Рассмотрим подробнее как происходит вставка нового значения в Dictionary:

При добавлении элемента вычисляется хэш-код Key объекта и формируется значение currentBucket'a на основании этого хэш-кода

В конце присваиваются значения новосозданному объекту

Схематически это будет Выглядить следующим образом:

insert

Если в buckets уже есть элемент с bucketNum, новый элемент добавляется в коллекцию, а индекс сохраняется в buckets, а индекс старого элемента в его поле next, сематически это выглядит вот так:

incert 2

Remove

Удаление со словаря представлено следующим кодом:

Как мы видим при удаленимы удаляем содержимое ячеек значениями по умолчанию, меняем указатели next других элементов при неоходимости и сохраняем индекс этого элемента во внутреннее поле freeList, а старое в поле next. Таким образом, при добавлении нового элемента мы можем повторно использовать такие свободные ячейки:

remove dictionary schema

Помните, что при очистке Dictionary, (метод Clear) его внутренний размер не изменяется. То есть, потенциально, вы можете тратить место.

Исходя из того что мы узнали давайте рассмотрим несколько примеров что я написал.

Первый пример когда в качестве ключа служит структура (для наглядности примера я переопределил метод GetHashCode который теперь всегда будет возвращать 0):

Что будет выведено в результате на экран?

Мы получим 3 записи, почему?

Давайте вспомним как работает Equals в структурах. Он сравнив значения всех свойств увидел что несмотря на то что str не менялась, а только изменилась str.Value определил что это другая структура и записал ее новым элементом словаря.

Теперь давайте рассмотрим другой пример, когда в качестве ключа используется класс:

В этот раз очевидно будет выведено всего 2 записи

Почему так произошло?

Класс это ссылочный тип, следовательно тот факт что мы изменили Value в классе, никак не влияет при его проверке методом Equals

ListDictionary

Это простая реализация IDictionary с использованием односвязного списка. Она меньше и быстрее, чем Hashtable, если количество элементов равно 10 или меньше. Лучше не использовать этот класс, если вам важна производительность для большого количества элементов.

Принимает в качестве параметров тип Object.

HybridDictionary

Гибридная версия между ListDictionary и HashTable . До 10 элементов гибрит использует ListDictionary элементов если же коллекция становится больше чем 10 элементов, он переключается на работу с HashTable

OrderedDictionary

Иногда бывают моменты когда вы хотите использовать ключи для поиска или foreach для итерации с помощью DictionaryEntry объектов. Элементы OrderedDictionary доступны с помощью ключа или индекса .Элементы OrderedDictionary не сортируются по ключу, в отличие от элементов SortedDictionary<TKey,TValue> класса который мы рассматриваем выше.

Вы можете видеть, что я использовал два разных метода, чтобы перебрать коллекцию. В первом примере я использовал цикл for и числовой индекс для извлечения каждого объекта (в данном случае строки), хранящегося в коллекции.

Другим преимуществом OrderedDictionary является скорость. При просмотре большой коллекции чтение OrderedDictionary с использованием первого примера, числового индекса, всегда будет быстрее, чем при использовании метода стиля словаря.

Когда вам нужна "мощь" коллекции и простой доступ к числовому индексу, OrderedDictionary является предпочтительной коллекцией.

SortedDictionary

Класс SortedDictionary<TKey, Tvalue> представляет дерево бинарного поиска, в котором все элементы отсортированы на основе ключа. Тип ключа должен реализовать интерфейс IComparable<TKey>. Если тип ключа не сортируемый, компаратор можно также создать, реализовав IComparer<TKey> и указав его в качестве аргумента конструктора сортированного словаря.

Классы SortedDictionary<TKey, Tvalue> и SortedList<TKey, TValue> часто сравнивают друг с другом, так как они имеют схожий функционал. Но поскольку SortedList<TKey, TValue> реализован в виде списка, основанного на массиве, a SortedDictionary<TKey, Tvalue> реализован как словарь, эти классы обладают разными характеристиками:

    SortedList<TKey, TValue> использует меньше памяти, чем SortedDictionary<TKey, TValue>

SortedDictionary<TKey, TValue> быстрее вставляет и удаляет элементы.

При наполнении коллекции отсортированными данными SortedList<TKey,TValue> работает быстрее, если при этом не требуется изменение размера.

Класс SortedDictionary<TKey, TValue> реализует интерфейсы IDictionary, IDictionary<TKey, TValue>, ICollection, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable и IEnumerable<KeyValuePair<TKey, TValue>> . В классе SortedDictionary<TKey, TValue> реализованы следующие конструкторы:

В первом конструкторе создается пустой словарь, во втором конструкторе — словарь с указанным количеством элементов dictionary. В третьем конструкторе допускается указывать с помощью параметра comparer типа IComparer способ сравнения, используемый для сортировки, а в четвертом конструкторе — инициализировать словарь, помимо указания способа сравнения.

В классе SortedDictionary<TKey, TValue> определен ряд методов. Некоторые наиболее часто используемые методы этого класса приведены ниже:

Add()

Добавляет в словарь пару "ключ-значение", определяемую параметрами key и value. Если ключ key уже находится в словаре, то его значение не изменяется, и генерируется исключение ArgumentException

ContainsKey()

Возвращает логическое значение true, если вызывающий словарь содержит объект key в качестве ключа; в противном случае — логическое значение false

ContainsValue()

Возвращает логическое значение true, если вызывающий словарь содержит значение value, в противном случае — логическое значение false

Remove()

Удаляет ключ key из словаря. При удачном исходе операции возвращается логическое значение true, а если ключ key отсутствует в словаре — логическое значение false

Следует иметь в виду, что ключи и значения, содержащиеся в коллекции, доступны отдельными списками с помощью свойств Keys и Values. В коллекциях типа SortedDictionary<TKey, TValue>.KeyCollection и SortedDictionary<TKey, TValue>.ValueCollection реализуются как обобщенные, так и необобщенные формы интерфейсов ICollection и IEnumerable.

StringDictionary

Предназначен для хеш-таблиц, в которых хранятся пары "ключ-значение", причем и ключ, и значение относятся к типу string. На данный момент этот класс является устрашевшим и не рекомендую вам его использовать в ваших приложениях.

ConcurrentDictionary

Представляет потокобезопасную коллекцию пар "ключ-значение", доступ к которой могут одновременно получать несколько потоков.

Для настройки есть 2 основных параметра:

сapacity — первоначальное кол-во элементов. По умолчанию — 31.

concurrencyLevel – предполагаемое число потоков на запись. По умолчанию = 4

Методы ConcurrentDictionary.

Основные Методы словаря можно разделить на 3 группы:

  • полностью неблокируемые;
  • блокировка одного элемента из пула блокировок;
  • блокировка всего словаря;

К полностью не блокируемым операциям можно отнести:

  • ContainsKey
  • TryGet
  • this [ ]
  • GetEnumerator – операция не обеспечивает целостность данных (не использует снепшоты), т.е. данные за время работы функции могут поменяться.

Все операции чтения (Get/ContainsKey) имеют примерно одинаковый алгоритм работы:

  • вычисление хеша ключа через GetHashCode()
  • вычисление бакета, в котором лежит наш элемент
  • сравнения значения ключа в бакете с тем, который у нас
  • чтение значения с использованием Volatile.Read

К операциям с блокировкой одного элемента из пула блокировок можно отнести:

  • TryAdd
  • TryUpdate
  • TryRemove

Ниже примерный алгоритм работы:

  • Вычисление хеша ключа нового элемента
  • Вычисление бакета bucketNo, в который будет добавлен элемент, и номера блокировки из пула
  • Блокировка bucketNo через Monitor.Enter
  • Запись элемента с использованием Volatile.Write
  • Освобождение блокировки Monitor.Exit

К самым неэффективным операциям, которые блокируют весь словарь, относятся:

  • Count, IsEmpty. Да, эти операции требуют полной блокировки словаря. Если вам необходимо сохранить в лог-файл число элементов, то можно использовать GetEnumerator и LINQ. Так же эти методы захватывают все локи в словаре. Лучше воздержаться от частого вызова этих свойств из нескольких потоков.
  • Keys, Values – получение списка ключей и списка значений соответственно. Они не только берут все локи, но и целиком копируют в отдельный List все ключи и значения. В отличие от традиционного Dictionary, одноимённые свойства которого возвращают «тонкие» обертки, здесь нужно быть готовым к крупным аллокациям памяти.
  • CopyTo – explicit ICollection
  • Clear, ToArray

В отличие от обычного Dictionary, можно производить вставку в ConcurrentDictionary или удаление из него прямо во время перечисления

Удалять элементы можно не только по ключу, но и по точному совпадению key + value, причем атомарно! Это недокументированная возможность, скрытая за explicit-реализацией интерфейса ICollection. Она позволяет безопасно очищать такой кэш даже в условиях гонки с обновлением значения:

в условиях конкурентного доступа GetOrAdd может вызвать делегат-фабрику для одного ключа сильно больше одного раза. Если так делать нельзя или дорого, достаточно обернуть значение в Lazy:

ImmutableDictionary и ReadOnlyDictionary

ReadOnlyDictionary можно инициализировать всего один раз через конструктор, После вы не сможете добавлять или удалять в него элементы. Это полезно, если вы хотите убедиться, что он не будет изменен, пока он будет отправлен через несколько уровней вашего приложения. Вы инициализируете ReadOnlyDictionary, передавая другой экземпляр слова конструктору. Это объясняет, почему ReadOnlyDictionary является изменяемым (если базовый словарь изменен). Это просто оболочка, защищенная от прямых изменений.

В ImmutableDictionary есть методы для его модификации, такие как " Add или " Remove , но они создадут новый словарь и вернут его, исходный останется без изменений и вернется копия нового неизменяемого словаря. ImmutableDictionary является потокобезопасным, потому что вы не можете изменить исходный экземпляр (ни прямо, ни косвенно). Все методы, которые "изменяют", фактически возвращают новый экземпляр.

Бенчмарки и итоги

Теперь давайте сравним быстродействие этих листов. ListDictionary исключен из тестов т.к он не эффективен для большого количества записей.

Читать:
Как отремонтировать вал коронатора

Тестирование проводили с 100000 записями, Код тестирования:

Первый тест на 100к записях:

Тип Операция Insert Операция Foreach Операция Update Операция Remove
Dictionary 5мс 1мс 1мс 2мс
ConcurrentDictionary 37мс 3мс 8мс 10мс
HybridDictionary 15мс 23мс 10мс 26мс
SortedDictionary 50мс 30мс 26мс 69мс
OrderedDictionary 55мс 10мс 89990мс 190522мс

Видим что OrderedDictionary безнадежно проигрывает по сравнению с остальными при обновлении и удалении.

Давайте проведем те же тесты но на 10М записей но уже без OrderedDictionary

Тип Операция Insert Операция Foreach Операция Update Операция Remove
Dictionary 491мс 168мс 178мс 275мс
ConcurrentDictionary 4652мс 239мс 548мс 635мс
HybridDictionary 2666мс 594мс 2835мс 1097мс
SortedDictionary 5829мс 2889мс 2797мс 8700мс

Если сравнить Dictionary с листом, то лист будет проигровать скорости вставки, поиска и удаления.

Обратите внимание на таблицу ниже, тут отображены скорость работы методов основных типов коллекций:compare collections

Словарь: класс Dictionary<TKey, TValue>

представляет собой сложную структуру данных, позволяющую обеспечить доступ к элементам по ключу. Главное свойство словарей — быстрый поиск на основе ключей. Можно также свободно добавлять и удалять элементы, подобно тому, как это делается в List<T>, но без накладных расходов производительности, связанных с необходимостью смещения последующих элементов в памяти.

На следующем рисунке представлена упрощенная модель словаря. Здесь ключами словаря служат идентификаторы сотрудников, такие как В4711. Ключ трансформируется в хеш. В хеше создается число для ассоциации индекса со значением. После этого индекс содержит ссылку на значение. Изображенная модель является упрощенной, поскольку существует возможность того, что единственное вхождение индекса может быть ассоциировано с несколькими значениями, и индекс может храниться в виде дерева.

Модель словаря C#

В .NET Framework предлагается несколько классов словарей. Главный класс, который можно использовать — это Dictionary<TKey, TValue>.

Тип ключа

Тип, используемый в качестве ключа словаря, должен переопределять метод GetHashCode() класса Object. Всякий раз, когда класс словаря должен найти местоположение элемента, он вызывает метод GetHashCode().

Целое число, возвращаемое этим методом, используется словарем для вычисления индекса, куда помещен элемент. Мы не станем углубляться в подробности работы этого алгоритма. Единственное, что следует знать — это то, что он использует простые числа, так что емкость словаря всегда выражается простым числом.

Реализация метода GetHashCode() должна удовлетворять перечисленным ниже требованиям:

Один и тот же объект должен всегда возвращать одно и то же значение.

Разные объекты могут возвращать одно и то же значение.

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

Он не должен генерировать исключений.

Он должен использовать как минимум одно поле экземпляра.

Значения хеш-кода должны распределяться равномерно по всему диапазону чисел, которые может хранить int.

Хеш-код не должен изменяться на протяжении времени существования объекта.

Чем вызвана необходимость равномерного распределения значений хеш-кода по диапазону целых чисел? Если два ключа возвращают хеш-значения, дающие один и тот же индекс, класс словаря вынужден искать ближайшее доступное свободное место для сохранения второго элемента, к тому же ему придется выполнять некоторый поиск, чтобы впоследствии извлечь требуемое значение. Понятно, что это наносит ущерб производительности, и если множество ключей дают одни и те же индексы, куда их следует поместить, вероятность конфликтов значительно возрастает. Однако благодаря способу, которым работает часть алгоритма, принадлежащая Microsoft, риск снижается до минимума, когда вычисляемое значение хеш-кода равномерно распределено между int.MinValue и int.MaxValue.

Помимо реализации GetHashCode() тип ключа также должен реализовывать метод IEquatable<T>.Equals() либо переопределять метод Equals() класса Object. Поскольку разные объекты ключа могут возвращать один и тот же хеш-код, метод Equals() используется при сравнении ключей словаря. Словарь проверяет два ключа А и В на эквивалентность, вызывая A.Equals(В). Это означает, что потребуется обеспечить истинность следующего утверждения:

Если истинно А.Equals(В) , значит, А.GetHashCode() и В.GetHashCode() всегда должны возвращать один и тот же хеш-код.

Класс Dictionary<TKey, TValue>

В классе Dictionary<TKey, TValue> реализуются интерфейсы IDictionary, IDictionary<TKey, TValue>, ICollection, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable, IEnumerable<KeyValuePair<TKey, TValue>>, ISerializable и IDeserializationCallback. В двух последних интерфейсах поддерживается сериализация списка. Словари имеют динамический характер, расширяясь по мере необходимости.

В классе Dictionary<TKey, TValue> предоставляется немало конструкторов. Ниже перечислены наиболее часто используемые из них:

В первом конструкторе создается пустой словарь с выбираемой по умолчанию первоначальной емкостью. Во втором конструкторе создается словарь с указанным количеством элементов dictionary. А в третьем конструкторе с помощью параметра capacity указывается емкость коллекции, создаваемой в виде словаря. Если размер словаря заранее известен, то, указав емкость создаваемой коллекции, можно исключить изменение размера словаря во время выполнения, что, как правило, требует дополнительных затрат вычислительных ресурсов.

В классе Dictionary<TKey, TValue> определяется также ряд методов:

Add()

Добавляет в словарь пару «ключ-значение», определяемую параметрами key и value. Если ключ key уже находится в словаре, то его значение не изменяется, и генерируется исключение ArgumentException

ContainsKey()

Возвращает логическое значение true, если вызывающий словарь содержит объект key в качестве ключа; а иначе — логическое значение false

ContainsValue()

Возвращает логическое значение true, если вызывающий словарь содержит значение value; в противном случае — логическое значение false

Remove()

Удаляет ключ key из словаря. При удачном исходе операции возвращается логическое значение true, а если ключ key отсутствует в словаре — логическое значение false

Кроме того, в классе Dictionary<TKey, TValue> определяются собственные свойства, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Эти свойства приведены ниже:

Comparer

Получает метод сравнения для вызывающего словаря

Keys

Получает коллекцию ключей

Values

Получает коллекцию значений

Следует иметь в виду, что ключи и значения, содержащиеся в коллекции, доступны отдельными списками с помощью свойств Keys и Values. В коллекциях типа Dictionary<TKey, TValue>.KeyCollection и Dictionary<TKey, TValue>.ValueCollection реализуются как обобщенные, так и необобщенные формы интерфейсов ICollection и IEnumerable.

И наконец, в классе Dictionary<TKey, TValue> реализуется приведенный ниже индексатор, определенный в интерфейсе IDictionary<TKey, TValue>

Этот индексатор служит для получения и установки значения элемента коллекции, а также для добавления в коллекцию нового элемента. Но в качестве индекса в данном случае служит ключ элемента, а не сам индекс. При перечислении коллекции типа Dictionary<TKey, TValue> из нее возвращаются пары «ключ-значение» в форме структуры KeyValuePair<TKey, TValue>. Напомним, что в этой структуре определяются два поля.

В этих полях содержится ключ или значение соответствующего элемента коллекции. Как правило, структура KeyValuePair<TKey, TValue> не используется непосредственно, поскольку средства класса Dictionary<TKey, TValue> позволяют работать с ключами и значениями по отдельности. Но при перечислении коллекции типа Dictionary<TKey, TValue>, например, в цикле foreach перечисляемыми объектами являются пары типа KeyValuePair.

Словарь в СИ Шарп

Разработка программного обеспечения – процесс, требующий от программиста определенного багажа знаний, навыков и умений. Первое, что необходимо сделать – определиться с языком. Второе – изучить его особенности. Только после этого можно полноценно создать контент для той или иной платформы.

Неплохим спросом в 21 веке пользуется СИ-семейство. Оно включает в себя немало диалектов: C, C++, C#. Последний начал набирать популярность в последние годы. Он разработан компанией Microsoft в 2001 году специально для платформы .Net Framework. Относится к объектно-ориентированным.

В процессе использования Си Шарп, который по синтаксису напоминает Java и C++, необходимо применять его разнообразные компоненты и возможности. Пример – статическая типизация, события, обобщенные типы и исключения. Огромную роль для продвинутого разработчика будет играть так называемый словарь.

В данной статье речь зайдет о том, что собой представляет dictionary C Sharp, как им пользоваться. Соответствующие сведения пригодятся не только новичкам, но и более опытным программистам на выбранном ЯП.

Определение

Dictionary – это сложная структура данных, которая позволяет обеспечить доступ к элементам по так называемому ключу. В Си Шарп для ее использования существует целая библиотека. Она носит название «коллекция Dictionary<K,V>».

В соответствующем компоненте каждый элемент – это связка «ключ-значение». Основной предназначение – получение значения по его ключу. Представлен соответствующая коллекция своеобразной хеш-таблицей. Получение значения элемента через ключ производится очень быстро, приближенно к О (1). Скорость извлечения «параметра» (V) находится в прямой зависимости от качества используемого алгоритма хеширования для типа, прописанного для ключа (K).

При работе с dictionary необходимо учесть следующее:

  • основное свойство – это быстрый поиск элементов на основе keys;
  • в процессе применения коллекции и соответствующего класса допустимо добавлять и удалять элементы;
  • при корректировке имеющихся элементов у устройства забирается часть памяти – это отражается на производительности.

Dictionaries – полезная коллекция, облегчающая разработку программного обеспечения. Главное знать, как правильно ее задействовать при составлении кода.

Упрощенная модель – пример

Ниже – упрощенная модель словаря в Си Шарп. Здесь ключи – это идентификаторы сотрудников. Они формируются в хеш. Далее происходит создание числа для ассоциаций индекса со значением. Index будет содержать ссылку на значение.

Соответствующий пример – упрощенный вариант. Связано это с тем, что существует возможность того, что единственное вхождение индекса ассоциируется с несколькими значениями. Index предусматривает хранение под видом своеобразного дерева.

При работе с .Net Framework можно задействовать сразу несколько классов словаря. Главный среди них – Dictionary<TKey, TValue>.

О типах ключа

Dictionary tkey может быть разного типа. Главное условие здесь – предопределение метода GetHashCode() класса Object. Каждый раз, когда соответствующий class словаря должен обнаружить нахождение элемента, осуществляется вызов упомянутого метода.

Полученный результат будет применяться словариком для вычисления индекса размещения интересующего компонента. Здесь достаточно усвоить то, что в процессе задействованы простые числа. Емкость dictionary будет выражаться соответствующими значениями.

При реализации GetHashCode() требуется удовлетворить такие запросы:

  1. Один объект возвращает при любых обстоятельствах одно и то же значение.
  2. Разные объекты предусматривают возможность возврата одного и того же «параметра».
  3. Метод выполняется быстро. Настолько, что его реализация не требует серьезных вычислительных затрат.
  4. В процессе не генерируются исключения.
  5. Значения хеш-кода распределяются равномерно в пределах всего диапазона чисел, предусмотренных хранением dictionary int.
  6. Хеш-код – это константа. Он не меняется в течение всего времени существования объекта.

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

Подобное поведение приводит к серьезному ущербу производительности. Если key множество дает один и те же indexes, возникает рост вероятности возникновения критических ошибок.

Кроме GetHashCode() тип ключа должен реализовывать метод IEquable<T>.Equals() или проводить переопределение метода Equals() класса Object. Соответствующий компонент будет применяться для сравнения ключей dict. Словарь проверяет keys A и B на схожесть, вызывая A.Equals(B). Это значит, что при истинности полученного сравнения A.GetHashCode() и B.GetHashCode() всегда возвращают один и тот же хеш-код.

Несколько слов о классе

Класс Dictionary<Tkey, TValue> реализовывает интерфейсы:

  • IDictionary;
  • IDictionary TKey, TValue;
  • ICollection;
  • ICollection<KeyValuePair<TKey, TValue>>;
  • IEnumerable;
  • IEnumerable< Keyvaluepair tkey, TValue>;
  • ISizeble;
  • IDeserializationCallback.

Два последних варианта имеют поддержку сериализации списков. Словари динамические. Они при необходимости могут расширяться.

Рассматриваемый класс предусматривает огромное множество конструкторов:

Выше – некоторые из них. Здесь:

  1. Первый конструктор создает пустой dict с выбранной первоначальной емкостью. Она задается заранее.
  2. Второй вариант отвечает за формирование «коллекции» с прописанным количеством элементов.
  3. Третий через параметр capacity указывает емкость collection, которая создается в виде dict. Если размер известен заранее, путем задания емкости можно исключать корректировку «объема» словарика при выполнении.

Все это поможет оптимизировать поиск необходимой информации при обработке программного кода.

Методы

Рассматриваемый класс предусматривает разнообразные методы:

  1. Add (). Отвечает за добавление пар ключей словаря и их значений, которые определяются параметрами key и value. Если первый «элемент» находится в dictionary, его «параметр» не изменится. Это приведет к генерации исключения ArgumentException.
  2. ContainsKey (). При помощи данного метода можно вернуть логическую «истину», если dictionary имеет объект key в виде ключа. В противном случае ведется работа с false.
  3. ContainsValue (). Истина возвращается, если вызывающий словарь содержит параметр value.
  4. Remove(). Метод, отвечающий за непосредственное удаление ключа key. Если процесс прошел успешно, происходит возврат true. Когда ключ отсутствует – false.

Этой информации будет достаточно для того, чтобы начать полноценную работу с dictionary, а также для того, чтобы найти интересующий программиста элемент. Но есть еще весьма важные моменты, которые пригодятся новичкам и продвинутым разработчикам на Си Шарп.

Свойства

Рассматривая ключи и значения, dictionary и его элементы, нужно помнить – изучаемый класс предусматривает определение собственный свойств. Они дополняют те, что предоставляются реализованными интерфейсами.

В число таких свойств можно отнести:

  1. Comparer. Находит (получает) метод сравнения для вызывающего C словаря.
  2. Keys. Отвечает за получение коллекции keys.
  3. Values. Свойство, которое позволяет получить collections «параметров».

При работе с соответствующим элементом языка нужно учесть – параметры и keys доступны отдельными списками. Для этого необходимо использовать в коде свойства Keys и Values. Коллекции типа Dictionary<Tkey, TValue>.KeyCollection и Dictionary<TKey, TValue>.ValueCollection проходят реализацию в качестве обобщенных. Не обобщенно применяются формы интерфейсов ICollection, а также IEnumerable.

Индексатор

В рассмотренном классе Dictionary<TKey, TValue> используется еще один важный элемент – индексатор. Он определен в интерфейсе IDictionary<TKey, TValue>:

Он нужен для того, чтобы получить и установить «параметр» элемента коллекции. Помогает добавлять в collection новые составляющие. В виде индекса здесь выступит ключ элемента, а не сам index.

При перечислении коллекции типа Dictionary<TKey, TValue> из нее будут возвращаться пары key-value в виде формы структуры KeyValuePair<TKey, TValue> с определением двух полей:

Они содержат key или value соответствующих элементов коллекции. Структура KeyValuePair не имеет непосредственного применения. Связано это с тем, что средства класса Dictionary дают возможность отдельной работы с ключами и «параметрами». При перечислении коллекции типа Dictionary<K, V> (пример – в foreach) в виде перечисляемых элементов (объектов) предстанут пары вида KeyValuePair.

Пример кода

Ниже – пример использования рассмотренного компонента в Си Шарп:

При обработке соответствующего кода на экране появится следующий результат:

Основа быстрого изучения

Для того, чтобы лучше разобраться в выбранном направлении, можно посмотреть разнообразные уроки и почитать сопутствующую литературу. Это неплохой вариант для тех, кто уже хорошо освоился в разработке и программировании. А еще – для людей с хорошей самодисциплиной.

Лучшее решение для тех, кого интересуют словари в Си Шарп, а также count, collections и иные элементы языка – специализированные онлайн курсы.

Здесь в срок от нескольких месяцев до года пользователя научат писать программы с нуля. Есть возможность начать обучение в любое время. При желании – одновременно освоить сразу несколько направлений.

Онлайн курсы есть как для новичков, так и для более опытных разработчиков. На них могут рассказать о выбранном ЯП или его инструментах (в зависимости от типа программы). Данный прием дает возможность получения инновационной IT-профессии в сжатые сроки.

В процессе обучения будет богатая практика и сбор портфолио. Пользователи в конце курсов получат сертификаты, подтверждающие соответствующие знания и навыки.

Похожие статьи