Почему HashSet <T> приписывается MayLeakOnAbort, но Словарь <K, V> нет?

Я заметил, что при попытке запрограммировать CLR-процедуру для SQL Server, что HashSet не допускается из-за приписывания с помощью [HostProtectionAttribute(SecurityAction.LinkDemand, MayLeakOnAbort = true)]. Процедуры CLR SQL Server не позволяют использовать объекты, в которых установлен MayLeakOnAbort. Хорошо, поэтому есть некоторые классы, которые следует избегать в процедурах CLR, и, возможно, даже дважды подумайте об использовании вне процедур CLR. Странно, что Dictionary<K,V> не ограничено. Теперь, основываясь на моем понимании того, что такое HashSet и что такое словарь, я ожидаю, что словарь должен иметь всю сложность Hashset, а затем некоторые. Почему же этот Словарь не так ограничен? Я делаю свое "дважды подумать об использовании HashSet<T>" и серьезно рассматриваю использование словаря вместо этого, хотя я не пишу процедуру CLR и не нуждаюсь ни в чем, кроме набора, который можно быстро протестировать для членства в сложном ключе ( объектная ссылка для объекта, который не имеет никакого сравнения, определены интерфейсы хэширования или равенства). Мне лучше использовать Hashset или Dictionary? Разве Hashset отличается тем, что он позволит использовать классы без интерфейсов сравнения или равенства, основанные исключительно на адресах памяти или что-то, что может быть причиной того, что HashSet менее "чист"?

Ответы

Ответ 1

HashSet<T> содержит методы, такие как IntersectWith, которые реализованы с использованием небезопасного кода с помощью stackalloc. Dictionary<TKey, TValue> не содержит таких методов. Хотя можно пометить свою собственную сборку как небезопасную и избежать рискованных методов, я просто отказался и использовал Dictionary<T, bool> в SQL CLR-функциях, где все значения true, именно по этой причине.

Ответ 2

Словарь основан на HashTable, а не на HashSet. Хотя они концептуально очень похожи, реализация HashSet включает некоторые небезопасные методы, тогда как HashTable и Dictionary не делают.

Словарь использует HashTable прежде всего как средство ускорения поиска в пространстве ключей. Учитывая эффективную реализацию GetHashCode() в типе, используемом для вашего словарного ключа, поиск в словаре - это наилучшее временное время и наихудшее линейное время.

HashSet - это сборник для хранения только уникальных значений (без механизма привязки) и требует правильной работы GetHashCode в вашем классе.

HashTables и словари используются для поиска значений с помощью ключа. HashSets используются исключительно для поддержки набора уникальных объектов и не имеют механизма манипуляции.

Если вам не нужна гарантия уникальности или другие функции, предоставляемые чем-то, что реализует ISet, нет реальной причины использовать HashSet вместо массива или списка.

Если вам нужна возможность вывести ваши предметы из коллекции с помощью ключа, используйте HashTable или Dictionary (словарь предпочтительнее, поскольку он является общедоступным и, следовательно, вы не постоянно боксируете/распаковываете все).

См. эти ссылки для объяснений:

http://msdn.microsoft.com/en-us/library/bb397727 (v = vs .110).aspx

http://msdn.microsoft.com/en-us/library/4yh14awz (v = vs .110).aspx