Какие элементы класса коллекции dotnet могут быть перечислены в «порядке добавления» и получены с помощью ключа? - PullRequest
5 голосов
/ 21 октября 2008

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

Существует ли класс (если возможно, общий), к которому элементы могут быть добавлены с помощью ключа, а какие могут быть перечислены в порядке добавления или которые можно получить по ключу?

Разъяснение: я не хочу перечислять в Порядке ключей. Я хочу перечислить в порядке добавления. Это означает, что я хочу иметь возможность получать элементы с помощью перечисления на основе FIFO (первым пришел - первым вышел).

Ответы [ 4 ]

4 голосов
/ 21 октября 2008

Вы можете добиться желаемого эффекта, просто используя List, в котором ключи хранятся в порядке сложения. Затем вы можете перечислить этот список по порядку и получить значения из Dictionary.

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

3 голосов
/ 21 октября 2008

Во-первых, исходя из вашего основного предположения, вы правы. Обычный словарь не дает никаких гарантий относительно порядка перечисления.

Во-вторых, вам нужно быть осторожным при переходе по SortedDictionary с пользовательским маршрутом IComparer. Компаратор используется для равенства ключей, а также для сортировки коллекции. То есть, используя IComparer на основе порядка добавления, вы можете столкнуться с трудностями при извлечении элемента из SortedDictionary по значению ключа, он может в конечном итоге потеряться в дереве (которое является основой отсортированного словаря).

Если вы хотите пойти по пути C5 Generic Class Library, вы можете получить неплохой пробег из HashedLinkedList<KeyValuePair<T>> или HashedLinkedList<T>, если T самозабирается. Вы можете создать IEqualityComparer, который будет работать с ключом для генерации хеш-кода. Затем, извлекая фактическое значение, вы можете использовать Find(ref T x) с прототипом x (возможно, там, где установлен только ключ), который найдет сохраненный T и вернет его по ссылке за O (1) раз против O ( log n ) с SortedDictionary. Кроме того, будучи поддержанным LinkedList, он гарантированно перечисляет в порядке добавления (и вы можете указать, какое направление вы бы предпочли через C5 IDirectedEnumerable).

Надеюсь, это поможет.

0 голосов
/ 07 октября 2009

Тема уже устарела, но я искал коллекцию с таким же поведением (сохраняю порядок добавления элементов) И смог индексировать коллекцию по ключу. Ответ - абстрактный класс KeyedCollection <>! (в пространстве имен System.Collections.ObjectModel) Я запустил простой тест со словарем и этой ключевой коллекцией, добавив несколько раз, убрав один из середины и снова добавив элемент. KeyedCollection добавляет новый элемент в конец, словарь помещает его в исходное положение (я думаю, что там происходит какое-то хеширование)

0 голосов
/ 21 октября 2008

Вы можете создать свой собственный универсальный класс (и получить его из словаря <,> или SortedDictionary <,>) и реализовать собственную версию GetEnumerator (), в которой вы можете отсортировать словарь по ключу и вернуть отсортированные значения ( или если вы используете SortedDictionary, то он уже отсортирован).

Вы также можете использовать SortedList <,>, который в некоторых случаях лучше и легче, проверьте MSDN, чтобы узнать, что лучше всего соответствует вашим потребностям.

...